関連記事
Goメモ-502 (cgoメモ-01)(cgoヘッダ) - いろいろ備忘録日記
Goメモ-506 (cgoメモ-02)(cgoヘッダ) - いろいろ備忘録日記
Goメモ-507 (cgoメモ-03)(C.int) - いろいろ備忘録日記
Goメモ-508 (cgoメモ-04)(C言語の構造体) - いろいろ備忘録日記
GitHub - devlights/blog-summary: ブログ「いろいろ備忘録日記」のまとめ
概要
以下、自分用のメモです。
今回から複数回に渡って cgo についてメモしていこうと思います。
cgo は、文字通りGoからCにアクセスすることが出来るようになるものなのですが、とても便利な反面、結構クセが強いのでメモでも残しておかないとすぐ頭から消えてしまいそうだなって思いました。
Cgo is not Go
という格言があったりするので、Go界隈で標準で推奨されていない技術かもしれません。が、実務ではC言語で作成されたライブラリなどは山のようにあります。んで、プロジェクトの方針でGoで作り直すことも出来ない場合も多々あります。そのような場合に非常に便利です。
これからのサンプルは以下のリポジトリにアップしてありますので、良ければご参考ください。
今回は cgo で利用する C言語の文字列
というか char *
について。
cgo では、import "C"
をすることによって、C言語側の型が使えるようになります。
C言語側の文字列をcgoにて利用する場合は、C.CString
を利用します。
C.CString
は、内部で malloc()
によりヒープメモリを確保しているため
利用後に必ず C.free()
にてメモリを開放する必要があります。当然、C.free()
を利用するためには <stdlib.h>
のインクルードが必要です。
C.CString
は、C言語の (char *)
を表します。
サンプル
main.go
package main /* #include <stdio.h> #include <stdlib.h> #include <string.h> void pStr(const char *m) { printf("%s\n", m); } */ import "C" import ( "fmt" "unsafe" ) func main() { // // cgoにてC言語側の文字列を扱いたい場合は // C.CStringを利用する。 // // C.CStringは、内部でmallocを使ってヒープメモリを // 確保しているため、利用後は必ず C.free() にてメモリを開放する必要がある。 // // C.CStringは、C言語の世界の (char *) を表す。 // (unsafe.Pointer() は、C言語の世界の (void *) を表す) // var ( goStr = "this is go string" cStr = C.CString(goStr) ) // 必ず C.free() で開放する defer C.free(unsafe.Pointer(cStr)) fmt.Printf("%[1]v (%[1]T)\n", goStr) fmt.Printf("%[1]v (%[1]T)\n", cStr) C.pStr(cStr) }
Taskfile.yml
# https://taskfile.dev version: '3' tasks: default: cmds: - go run main.go
実行
$ task task: [default] go run main.go this is go string (string) 0x15e1140 (*main._Ctype_char) this is go string
参考情報
- C? Go? Cgo!
- Go Wiki: cgo
- cmd/cgo
- runtime/cgo
- cgoを使ったCとGoのリンクの裏側 (1)
- cgoを使ったCとGoのリンクの裏側 (2)
- ebitengine/purego
- JupiterRider/ffi
Goのおすすめ書籍
過去の記事については、以下のページからご参照下さい。
サンプルコードは、以下の場所で公開しています。