Go/cgoでGoのコードからCの関数を利用する

< Go

cgoでGoのコードからCの関数を利用する 編集

GoのコードからCの関数を利用するには、cgo という仕組みを使います[1]

Cの標準ライブラリー関数 div() をGoから呼びさせるようにした例 編集

Cの標準ライブラリー関数に、整数で分子と分母を与えると商と剰余を返す関数 div() があります。 Goの多値返しと似ているので、Goから呼べるようにしてみました。

Cの標準ライブラリー関数 div() をGoから呼出せるようにした例
package main

import (
        //#include <stdlib.h>
        "C"
        "fmt"
)

// div_t div(int num, int denom);
func div(n, d int) (int, int) {
        divmod := C.div(C.int(n), C.int(d))
        return int(divmod.quot), int(divmod.rem)
}

func main() {
        for i := 0; i <= 8; i++ {
                quot, rem := div(i, 3)
                fmt.Printf("%d / 3: %v .. %v\n", i, quot, rem)
        }
}
実行結果
0 / 3: 0 .. 0
1 / 3: 0 .. 1
2 / 3: 0 .. 2
3 / 3: 1 .. 0
4 / 3: 1 .. 1
5 / 3: 1 .. 2
6 / 3: 2 .. 0
7 / 3: 2 .. 1
8 / 3: 2 .. 2
解説
        "C"
cgo を使う時は疑似パッケージ "C" をインポートします。
これで、C.size_tなどの型、C.stdoutなどの変数、C.putcharなどの関数を参照することができます。
プリアンブル
        //#include <stdlib.h>
"C"のインポートの直前にコメントがある場合、そのコメントはプリアンブルと呼ばれパッケージのC部分をコンパイルする際のヘッダーとして使用されます。
この場合は div_t型の定義と div()関数の宣言のために、 stdlib.h をインクルードしています。
Cの関数呼び出し
        divmod := C.div(C.int(n), C.int(d))
Cの div() はGoからは C.div() として呼び出します。このとき引数は C.int のようなCの型に変換する必要があります。
戻値の変換
        return int(divmod.quot), int(divmod.rem)
Cに div() は div_t型の戻値を返すので、各メンバーをGoのint型に変換します。

脚註 編集

  1. ^ cgo command - cmd/cgo - pkg.go.dev” (2021年11月4日). 2021年11月29日閲覧。

参考文献 編集