2016/09/21

Recent entries from same category

  1. golang の http.Client を速くする
  2. Windows からも ssh でリモートコマンド実行したい、それ golang で出来るよ
  3. Matz の「言語のしくみ」を読んだ。
  4. コマンドラインアプリで OAuth2 認証を使う際に使えるテクニック
  5. gops が SIGINT をキャッチしてしまう問題が修正された。

以前から c-archive は作れたけど DLL にするとシンボルが被ったりして上手く DLL が作れなかった。

Big Sky :: golang の Windows 版が buildmode=c-archive をサポートした。

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

http://mattn.kaoriya.net/software/lang/go/20160405114638.htm
cmd/go: -buildmode=c-shared should work on windows · Issue #11058 · golang/go · GitHub
https://github.com/golang/go/issues/11058#issuecomment-248330515

-Wl,--allow-multiple-definition を知らなかった。

package main

import "C"

func main() {
}

//export HelloWorld
func HelloWorld() {
    println("Hello golang!")
}

まずこの様なソースコードを c-archive にして libxxx.a を作る。

go build -buildmode=c-archive -o libxxx.a xxx.go

次に HelloWorld をエントリにする def ファイルを作る。

LIBRARY   helloworld
EXPORTS
   HelloWorld

そして def ファイルを指定して DLL を生成する。この時 -Wl,--allow-multiple-definition を指定すること。

gcc -m64 -shared -o xxx.dll xxx.def libxxx.a -Wl,--allow-multiple-definition -static -lstdc++ -lwinmm -lntdll -lWs2_32

後は呼び出し元を作って...

package main

import "syscall"

var (
    lib        = syscall.NewLazyDLL("xxx.dll")
    helloworld = lib.NewProc("HelloWorld")
)

func main() {
    helloworld.Call()
}
Golang で DLL!

C言語からも

#include <windows.h>

typedef void (*pfn)(void);

int
main(int argc, char* argv[]) {
    pfn fn;
    HMODULE h = LoadLibrary("xxx.dll");
    fn = (pfn) GetProcAddress(h, "HelloWorld");
    fn();
    return 0;
}
Golang で DLL!

Golang のランタイムが FreeLibrary される事を想定していないので Vim の libcall からは直では呼び出せないけど libcallex-vim を使って解放なしに呼び出せば実行可能。ただしハンドルは持ちっぱなしにしないとリークする。

let xxx = libcallex#load("xxx.dll")
call xxx.call("HelloWorld", [], "")
"call xxx.free()

やったー!これで勝つる!

みんなのGo言語【現場で使える実践テクニック】 みんなのGo言語【現場で使える実践テクニック】
松木雅幸, mattn, 藤原俊一郎, 中島大一, 牧 大輔, 鈴木健太
技術評論社 / ¥ 2,138 (2016-09-09)
 
発送可能時間:在庫あり。


blog comments powered by Disqus