mac アプリに go のコードをリンクする

ios の場合は gomobile を使う必要がありますが、osx の場合は必要ないので go build -buildmode=c-archive したものをリンクすると mac アプリから呼ぶことが出来ます。

例えば適当に、 libdummy というディレクトリを作り main.go として以下のようなファイルを作ります。 c の世界に go の struct とかを持っていけないので、github.com/mattn/go-pointer を利用し、Save した結果 ( C.malloc(C.size_t(1)) の返り値 ) を c の世界に返します。

package main

import "C"

import (
    "github.com/mattn/go-pointer"
    "unsafe"
)

//export dummy
type dummy struct {
    i int
}

//export DummyCreate
func DummyCreate() unsafe.Pointer {
    return pointer.Save(&dummy{})
}

//export DummyDestroy
func DummyDestroy(p unsafe.Pointer) {
    pointer.Unref(p)
}

//export DummyAdd
func DummyAdd(p unsafe.Pointer, i C.int) {
    d := pointer.Restore(p).(*dummy)
    d.i += int(i)
}

//export DummyGet
func DummyGet(p unsafe.Pointer) C.int {
    return C.int(pointer.Restore(p).(*dummy).i)
}

func main() {}

$ go build -buildmode=c-archive すると、libdummy.a, libdummy.h が生成されるので、xcode 側でリンクするようにします。 ( Linked Frameworks and Libraries に libdummy.a を追加、 swift の場合は、Bridging Header で libdummy.h を include )

そうすると

        let d = DummyCreate()
        DummyAdd(d, 3)
        defer {
            DummyDestroy(d)
        }
        let i = "\(DummyGet(d))" // 3

こういう感じで呼べます。