2016/04/05

Recent entries from same category

  1. Go 言語プログラミングエッセンスという本を書きました。
  2. errors.Join が入った。
  3. unsafe.StringData、unsafe.String、unsafe.SliceData が入った。
  4. Re: Go言語で画像ファイルか確認してみる
  5. net/url に JoinPath が入った。

だいぶ時間が掛かった様ですが、ようやく buildmode=c-archive が Windows でも使える様になりました。

cmd/go: -buildmode=c-archive should work on windows · Issue #13494 · golang/go · GitHub

32-bit is also important to me. I'd like to help. I'm seeing those same link errors when I enable it...

https://github.com/golang/go/issues/13494

まだ buildmode=c-shared (いわゆる dll) はビルド出来ないけど、ひとまずC言語から golang のライブラリをリンクして動かせる様になりました。例えばこんな事が出来ます。

package main

import "C"

import (
    "fmt"
    "github.com/mattn/go-haiku"
)

var (
    q = make(chan string)
)

func init() {
    go func() {
        for {
            fmt.Println(<-q)
        }
    }()
}

//export PrintHello
func PrintHello(p *C.char) {
    q <- C.GoString(p)
}

//export IsHaiku
func IsHaiku(p *C.char) C.int {
    var ret C.int
    if haiku.Match(C.GoString(p), []int{575}) {
        ret = 1
    }
    return ret
}

//export PrintLine
func PrintLine(p *C.char) {
    fmt.Println(C.GoString(p))
}

func main() {
}

この様なソースコード lib.go を用意し以下の手順で lib.a を作ります。

go build -buildmode=c-archive lib.go

そしてC言語からは以下の様に呼び出します。

#include <stdio.h>

int
main(int argc, char* argv[]) {
  extern void PrintHello(char*);
  PrintHello("hello");
  PrintHello("hello");
  PrintHello("hello");
  PrintHello("hello");
  PrintHello("hello");
  Sleep(3000);
  return 0;
}

ビルドは以下の様になります。

gcc -o example.exe example.c lib.a -lws2_32 -lntdll

goroutine と channel を使っているので PrintHello の呼び出しは非同期に画面出力されます。golang では簡単に扱えるけどC言語だと若干手間だなと思える様な処理もリンクするだけで使える様になります。以下は ikawaha さんの kagome を使って俳句を扱えるライブラリ go-haiku をC言語から呼び出しています。

#include <stdio.h>

int
main(int argc, char* argv[]) {
  extern void PrintLine(char*);
  extern int IsHaiku(char*);

  char* s = "古池や蛙飛び込む水の音";

  PrintLine(s);
  if (IsHaiku(s)) {
    PrintLine("それ575じゃん");
  }
  return 0;
}
古池や蛙飛び込む水の音
それ575じゃん

めちゃめちゃ簡単ですね。

Posted at by