関連記事
Goメモ-502 (cgoメモ-01)(cgoヘッダ) - いろいろ備忘録日記
Goメモ-506 (cgoメモ-02)(cgoヘッダ) - いろいろ備忘録日記
Goメモ-507 (cgoメモ-03)(C.int) - いろいろ備忘録日記
Goメモ-508 (cgoメモ-04)(C言語の構造体) - いろいろ備忘録日記
Goメモ-509 (cgoメモ-05)(C.CString)(Cの文字列) - いろいろ備忘録日記
Goメモ-510 (cgoメモ-06)(C.GoString)(Cの文字列をGoの文字列へ) - いろいろ備忘録日記
Goメモ-511 (cgoメモ-07)(C.CBytes)([]byteをCのバイト列に) - いろいろ備忘録日記
GitHub - devlights/blog-summary: ブログ「いろいろ備忘録日記」のまとめ
概要
以下、自分用のメモです。
今回から複数回に渡って cgo についてメモしていこうと思います。
cgo は、文字通りGoからCにアクセスすることが出来るようになるものなのですが、とても便利な反面、結構クセが強いのでメモでも残しておかないとすぐ頭から消えてしまいそうだなって思いました。
Cgo is not Go
という格言があったりするので、Go界隈で標準で推奨されていない技術かもしれません。が、実務ではC言語で作成されたライブラリなどは山のようにあります。んで、プロジェクトの方針でGoで作り直すことも出来ない場合も多々あります。そのような場合に非常に便利です。
これからのサンプルは以下のリポジトリにアップしてありますので、良ければご参考ください。
今回は cgo で利用する C.GoBytes
について。
cgo では、import "C"
をすることによって、C言語側の型が使えるようになります。
C.GoBytes()
は、Cのバイト列をGoのバイトスライスに変換します。渡す際はC側のバイト列を void *
つまり unsafe.Pointer
で渡します。戻り値は[]byte
となります。
C.CBytes()
と違い、Go側でメモリ確保しているので C.free()
の呼び出しは必要ありません。
サンプル
main.go
package main /* #include <stdio.h> #include <stdlib.h> #include <string.h> const int BUF_SIZE = 15*sizeof(char); void *buf; void myAlloc() { // MEMO: エラー処理は割愛 buf = malloc(BUF_SIZE); memset(buf, 0, BUF_SIZE); } void myAssign() { strncpy(buf, "hello C World", BUF_SIZE); } void myPrint() { printf("[C ] %s %d\n", (char *)buf, BUF_SIZE); } void myFree() { free(buf); } */ import "C" import ( "encoding/hex" "fmt" "unsafe" ) func main() { // // C側でメモリを確保しバッファにデータを埋める // C.myAlloc() defer C.myFree() C.myAssign() C.myPrint() // // Go側の[]byteとして取得 // var ( cBuf unsafe.Pointer = C.buf goBuf []byte = C.GoBytes(cBuf, C.BUF_SIZE) ) fmt.Printf("[GO] %s %d\n", string(goBuf), len(goBuf)) fmt.Printf("[GO] %v\n", hex.Dump(goBuf)) }
Taskfile.yml
# https://taskfile.dev version: '3' tasks: default: cmds: - go run main.go
実行
$ task task: [default] go run main.go [C ] hello C World 15 [GO] hello C World 15 [GO] 00000000 68 65 6c 6c 6f 20 43 20 20 57 6f 72 6c 64 00 |hello C World.|
参考情報
- C? Go? Cgo!
- Go Wiki: cgo
- cmd/cgo
- runtime/cgo
- cgoを使ったCとGoのリンクの裏側 (1)
- cgoを使ったCとGoのリンクの裏側 (2)
- ebitengine/purego
- JupiterRider/ffi
Goのおすすめ書籍
過去の記事については、以下のページからご参照下さい。
サンプルコードは、以下の場所で公開しています。