Страницы

понедельник, 27 февраля 2012 г.

Binding: Go & C

Я уже писал о своем интересе к Go. Чуть больше недели назад поставил Ubuntu (с помощью wubi), и начал разбираться как можно написать работающий Helloworld, в котором С-шная функция будет вызываться кодом написанным на Go.
Мне это нужно потому, что для Go нет никаких графических движков, а на С их немало написано. К счастью в go есть специальная программа для связывания Go и С - CGO. Но я немало поломал голову, прежде чем получил хоть какие-то результаты.

Начал я с попыток скомпилироваться,  запуская cgo из терминала. Ничего не вышло, изучение ошибок тоже ничего не дало. Перерыв весь доступный материал по cgo (а его очень немного: описание команды, статья в go-wiki и статья в блоге с кратким мануалом, в которых только самые азы даются - как приводить типы, как использовать  псевдо-пакет import "C"; все остальное - это обсуждения на форумах) я не нашел ничего полезного. Очень помог хороший пост, вовремя попавшийся на глаза (к сожалению, ссылку потерял, поищу, выложу чуть позже), в котором был пример работы с CGO с использованием Makefile-а. Оттуда я узнал, что в Go есть 2 стандартных include для Makefile:
$GOROOT/src/Make.inc
$GOROOT/src/Make.pkg 
В Make.pkg оказались неплохие коментарии на счет того как работает cgo. После этого дело сдвинулось с мертвой точки.
Работающий Makefile у меня вышел такой:

#This is magic! Этот файл много чего делает. В частности обьявляет много полезных переменных, таких как:
#$GC, $GL, $O - имена компилятора, линковщика, расширения обьектных файлов на данной архитектуре
#Должно быть удобно когда проект понадобиться собирать на другой машине - Makefile будет минимально меняться
include $(GOROOT)/src/Make.inc

#это настраивает для какой архитектуры компилировать
PKGDIR=$(GOROOT)/pkg/$(GOOS)-$(GOARCH)

#Имя пакета, который будет собран cgo
TARG=calc

#Список всех cgo файлов. У меня только один такой.
#Все, что он делает - оборачивает 2 int в С.int и передает их в calc.h (пока что в .h файл я вкинул и реализацию, потом попробую разнести)
CGOFILES=calc.go

#Еще один magic. Именно он отвечает за вызов cgo
include $(GOROOT)/src/Make.inc

#Добавляем файлы чтобы make clean работало как надо. Я это просто скопировал из примера
CLEANFILES+=$(PKGDIR)/$(TARG).a

#Объявляем конечный Target.  Он имеет 2 требования:
# install - это требование выполнить сборку всех  CGOFILES и закинуть их в $(PKGDIR)
# main.go - файл должен существовать
# Потом calc.a уже готов и лежит где надо, компилируем main.go. 
# Собираем все вместе линковщиком $(GL) в исполняемый файл "main".
main: install main.go
        $(GC) main.go
        $(GL) -o $@ main.$O
(Если кто-то будет копировать - не забудьте заменить пробелы перед  $(GC), $(GL) на TAB!)

Далее "make main", и все готово.
P.S. позже выложу код на github и дам ссылку

Комментариев нет:

Отправить комментарий