참고: SWIG를 사용하면 cgo보다 더 편하게 C 코드를 호출할 수 있고, 또 C++도 호출 가능한것 같다. 그런데 아직 문서가 제대로 안 만들어진것 같은데, 예제 코드는 $GOROOT/misc/swig/ 디렉토리를 참조한다. 그리고 SWIG 사이트에서 Go를 지원하는 내용을 간단하게 정리한 문서는 여기를 참조한다. SWIG 2.0부터 지원하는것 같은데 우분투 10.10에 설치된 SWIG는 버전이 낮아서 Go를 지원하지 않는다.
먼저 C 코드를 호출하는 루틴을 별도 패키지로 작성한다. 여기서는 cgotest라는 이름으로 만든다. 이 패키지는 CgoTest() 메소드를 가지는데, 문자열을 출력하고 0을 리턴하는 간단한 C 함수(f)를 호출한다. cgotest.go 파일을 생성하고 아래 내용을 입력하자.
package cgotest
/*
#include <stdio.h>
int f(const char *str)
{
printf("%s\n", str);
return 0;
}
*/
import "C"
import "fmt"
import "os"
func CgoTest(s string) {
str := C.CString(s)
r, err := C.f(str)
if err != nil {
fmt.Printf("error: %v\n", err)
os.Exit(1)
}
fmt.Printf("ret: %v\n", r)
}
그리고 cgotest 패키지를 사용하는 main 코드를 생성한다. cgomain.go 파일을 생성하고 아래 내용을 입력한다.
package main
import "cgotest"
func main() {
cgotest.CgoTest("test")
}
마지막으로 Makefile을 생성하고 아래 내용을 입력한다. 단, 주의할 점은 들여쓰기는 반드시 탭으로 구성되어 있어야 한다.
include $(GOROOT)/src/Make.inc
TARG=cgotest
CGOFILES=\
cgotest.go
CLEANFILES+=cgomain
include $(GOROOT)/src/Make.pkg
all: cgomain
cgomain: install cgomain.go
$(GC) cgomain.go
$(LD) -o $@ cgomain.$O
참고로 위 Makefile은 cgotest.a 파일을 $GOROOT/pkg/linux_amd64 디렉토리에 복사를 한다. 그래서 이후에 6g나 6l에서 cgotest 패키지를 사용할 수 있도록 만들어준다. 만약 이와 같이 패키지 파일을 $GOROOT 밑으로 복사하고 싶지 않다면, 아래와 같이 Makefile의 cgomain: 부분을 수정해서 임시 파일을 사용하도록 변경한다.
cgomain:
$(GC) -I_obj cgomain.go
$(LD) -L_obj -o $@ cgomain.$O
이제 쉘에서 make를 치면 cgo 프로그램이 실행되면서 C 코드와 연동되는 임시 코드를 생성하고, 최종적으로 이 패키지를 사용하는 cgomain 바이너리를 생성한다.
superkkt@~/tmp/go$ make
CGOPKGPATH= cgo -- cgotest.go
touch _obj/_cgo_run
6g -o _go_.6 _obj/cgotest.cgo1.go _obj/_cgo_gotypes.go
6c -FVw -I/usr/local/go/pkg/linux_amd64 -I . -o "_cgo_defun.6" _obj/_cgo_defun.c
gcc -m64 -I . -g -fPIC -O2 -o _cgo_main.o -c _obj/_cgo_main.c
gcc -m64 -I . -g -fPIC -O2 -o cgotest.cgo2.o -c _obj/cgotest.cgo2.c
gcc -m64 -I . -g -fPIC -O2 -o _cgo_export.o -c _obj/_cgo_export.c
gcc -m64 -g -fPIC -O2 -o _cgo1_.o _cgo_main.o cgotest.cgo2.o _cgo_export.o
cgo -dynimport _cgo1_.o >_obj/_cgo_import.c_ && mv -f _obj/_cgo_import.c_ _obj/_cgo_import.c
6c -FVw -I . -o "_cgo_import.6" _obj/_cgo_import.c
rm -f _obj/cgotest.a
gopack grc _obj/cgotest.a _go_.6 _cgo_defun.6 _cgo_import.6 cgotest.cgo2.o _cgo_export.o
cp _obj/cgotest.a "/usr/local/go/pkg/linux_amd64/cgotest.a"
6g cgomain.go
6l -o cgomain cgomain.6
이제 생성된 cgomain 바이너리를 실행해보자. C 코드와 연동된 코드가 정상적으로 실행되는걸 확인할 수 있다.
superkkt@~/tmp/go$ ./cgomain
test
ret: 0
<References>

comments
comments rss (+댓글 쓰러가기)