Edited at

CGO の書き方、コンパイル時に必要な環境変数、指定できるオプション、ライブラリの使い方など

C++ で書かれたライブラリを Go から使うために CGO を使ったときの知見をちょろちょろまとめます。

C も Go も初心者の域を脱していないので、単に C の文法の問題だったりすることがあるかもしれません


CGO コードの書き方関連


import C の前には空行を入れない

Go の中に C のコードを書くことができるが、そのときに必要な注意。

https://golang.org/cmd/cgo/#hdr-Using_cgo_with_the_go_command にも書いてある

// #include <stdio.h>

// #include <errno.h>
import "C"

のように、空行は入れずに書く


C / C++ のコンパイラに渡すオプション(flag)を記述する CFLAGS

import C の上に CFLAGS を書く。

// #cgo CFLAGS: -I/usr/local/lib

import C


CGO build 関連


ビルドするには CGO_ENABLED

go run で動かしていたコードも、 go build でバイナリを作るときには CGO_ENABLED という環境変数に1を入れないといけない。

これを怠ると、「同じパッケージの別ファイルに書いた関数や定数が読めない」という問題が出て、マジで意味がわからなくなる。


コンパイラの指定 CC

環境変数 CC に、コンパイルに必要な gcc 的なものを指定する。

C++ のコードをコンパイルして参照したいからといって CCg++ 系を指定すると、

# runtime/cgo

gcc_libinit.c: In function 'int _cgo_try_pthread_create(pthread_t*, const pthread_attr_t*, void* (*)(void*), void*)':
gcc_libinit.c:110:21: error: invalid conversion from 'void*' to 'timespec*' [-fpermissive]
nanosleep(&ts, nil);
^

こういう問題に出くわす。これを読んで解決した。 https://github.com/bazelbuild/rules_go/issues/1320

CXX を使えばいいかとかそういうことはちょっと調べきれていない。