いろいろ備忘録日記

主に .NET とか Go とか Flutter とか Python絡みのメモを公開しています。

Goメモ-522 (cgoメモ-15)(Goでsoファイルを作成してC言語から呼び出し)

関連記事

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のバイト列に) - いろいろ備忘録日記

Goメモ-512 (cgoメモ-08)(C.GoBytes)(Cのバイト列をGoの[]byteへ) - いろいろ備忘録日記

Goメモ-514 (cgoメモ-09)(C.GoStringN)(C.GoStringのサイズ指定版) - いろいろ備忘録日記

Goメモ-515 (cgoメモ-10)([]byteを(void *)へ変換) - いろいろ備忘録日記

Goメモ-516 (cgoメモ-11)([]byteを(char *)へ変換) - いろいろ備忘録日記

Goメモ-518 (cgoメモ-12)(Cのmallocをcgo経由で呼び出し) - いろいろ備忘録日記

Goメモ-519 (cgoメモ-13)(ポインタ演算) - いろいろ備忘録日記

Goメモ-520 (cgoメモ-14)(Goの関数をCの世界に公開 (export)) - いろいろ備忘録日記

GitHub - devlights/blog-summary: ブログ「いろいろ備忘録日記」のまとめ

概要

以下、自分用のメモです。

今回から複数回に渡って cgo についてメモしていこうと思います。

cgo は、文字通りGoからCにアクセスすることが出来るようになるものなのですが、とても便利な反面、結構クセが強いのでメモでも残しておかないとすぐ頭から消えてしまいそうだなって思いました。

Cgo is not Go

という格言があったりするので、Go界隈で標準で推奨されていない技術かもしれません。が、実務ではC言語で作成されたライブラリなどは山のようにあります。んで、プロジェクトの方針でGoで作り直すことも出来ない場合も多々あります。そのような場合に非常に便利です。

これからのサンプルは以下のリポジトリにアップしてありますので、良ければご参考ください。

github.com

今回は Go側の関数を公開してsoファイルを作成し、それをC言語側から呼び出す方法について。

cgoでは、Goの関数直上のコメントにて

//export function-name

とすると、この関数をC側にエクスポートすることが出来ます。つまり、C言語の方からGoで定義された関数を呼べるようになります。

Goで、soファイルを作成するには go build にて -buildmodec-shared を指定してビルドします。

こんな感じ。

$ go build -o libxxx.so -buildmode=c-shared main.go

以下の記事もよかったら、ご参考まで。

Goメモ-356 (Go側からsoファイルを作成してPythonとCで利用)(c-shared)

サンプル

main.go

package main

/*
 */
import "C"

//export add
func add(x, y C.int) C.int {
    var (
        p1  = int(x)
        p2  = int(y)
        ans = p1 + p2
    )
    return C.int(ans)
}

func main() {}

app.c

#include <stdio.h>
#include <stdlib.h>

extern int add(int, int);

int main(void) {
    int x = 10;
    int y = 20;
    int z = add(x, y);

    printf("%d\n", z);
    
    return EXIT_SUCCESS;
}

Taskfile.yml

# https://taskfile.dev

version: '3'

vars:
  GREETING: Hello, World!

tasks:
  default:
    cmds:
      - task: run
  run:
    deps: [ build ]
    cmds:
      - ./app
    env:
      LD_LIBRARY_PATH: .
  build:
    cmds:
      - task: build-c
  build-c:
    deps: [ build-sofile ]
    internal: true
    cmds:
      - gcc -o app app.c -I. -L. -lapp
  build-sofile:
    internal: true
    cmds:
      - go build -o libapp.so -buildmode=c-shared main.go

実行

$ task
task: [build-sofile] go build -o libapp.so -buildmode=c-shared main.go
task: [build-c] gcc -o app app.c -I. -L. -lapp
task: [run] ./app
30

参考情報

Goのおすすめ書籍


過去の記事については、以下のページからご参照下さい。

サンプルコードは、以下の場所で公開しています。