Help us understand the problem. What is going on with this article?

Golang で Shared Library を出力する。

More than 5 years have passed since last update.

Go 1.4 で android に対応していたのでもしかしてそろそろできるんじゃないかなぁとか思いながら github の go レポジトリを眺めていたら Go 1.5 から buildmode なんていうオプションが追加されていて、そこに c-shared なるものががが。

https://github.com/golang/go/blob/ae3e3610d5ea9814fcc8bff5c4cea51795465565/src/cmd/go/build.go#L326

これは間違いないだろうと試してみました。
(ちなみに試すためには Go 1.5 が必要なので git clone して Go 1.4 でビルドしてください。本記事では Go 1.5 の準備は割愛します。)

サンプルコードは gist にも上げておきました。

libgofib.go
package main

import (
    "C"
    "log"
)

//export fib
func fib(n int) int {
    if (n < 2) { return n }
    return fib(n - 2) + fib(n - 1)
}

func init() {
    log.Println("Loaded!!")
}

func main() {
}

内容は単純なフィボナッチです。
ポイントは下記の4点です。

  • パッケージは main でないと生成できない。
  • main関数は実行されないが宣言する必要がある。
  • エクスポートしたい関数にコメントで「//export funcname をつける。」(cgoと同じ)
  • init は ライブラリロード時に実行される。

後は buildmode=c-shared を付けてビルドするだけ!
(Go 1.5 は即席で用意しただけなので、GOROOTをビルド時に設定してます。)

GOROOT=$PWD/go ./go/bin/go build -buildmode=c-shared -o libgofib.so libgofib.go

相変わらずのでかいバイナリが出力されればビルドできてます。

$ ll libgofib.so 
-rwxrwxr-x 1 yanolab yanolab 3.2M  5月 21 09:46 libgofib.so*

$ file libgofib.so 
libgofib.so: ELF 64-bit LSB  shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=acc56aca625aa6e9bf7bfc9d7b1c8e377ff9df0b, not stripped

サイズが大きかったのでまさか Shared Library まで他ライブラリに依存していないのか!と思いましたがそんなことはありませんでした。

$ ldd libgofib.so 
    linux-vdso.so.1 =>  (0x00007ffc0d6f7000)
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fc878e8a000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fc878ac5000)
    /lib64/ld-linux-x86-64.so.2 (0x00007fc879563000)

まぁ、しょうが無いですよね。うん。

せっかくなので、このライブラリを実行するところまで確認してみます。
まずは fib がちゃんとエクスポートされているかどうか。

$ nm -D libgofib.so | grep fib
00000000000d9eb0 T _cgoexp_28da6a1ce835_fib
00000000000d9a50 T fib

バッチリですね。

次は実際にこの関数を呼び出してみます。
ライブラリの関数を簡単に実行する方法としてはあれしかないです。そう、僕らの python 先生。
おもむろに python インタプリタを起動して下記のコードを打ち込みます。

>>> import ctypes
>>> lib = ctypes.CDLL("./libgofib.so")
>>> 2015/05/21 09:56:21 loaded!!

>>> lib.fib(32)
2178309

バッチリ使えてますね。
プラットフォームが linux/{arm,amd64}, android/arm に限定されてたりしますが、チャネルも goroutine も使えるので、中身をバリバリの Go で書いて簡単な C API を提供するとか個人的にはすごくポイント高いです。
今後の展開にも大いに期待したいです。

P.S. 2015年5月21日現在、Go 1.5 はリリースされていないので、リリース時にどうなるかはわかりませんので悪しからず。

yanolab
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした