« macでもgo言語でX11に描画してみるメモ | メイン | Thunderbird3があまりに重いのでグローバル検索を止めて高速化するメモ »

go言語でgosqlite3を使ってみるためのcgoへのパッチ

以下のパッチは2/23現在不要なようです。

go言語でもsqlite3を使ってみたいと思い探してみると、いくつか既に拡張を作っている方がいたので以下のものをゲットしてみたのですが、残念ながらコンパイルエラー。

原因を調べてみるとgoからC言語のライブラリを呼び出すラッパー生成ツールのcgoによって生成された_cgo_gotypes.goで型の前方参照をしており定義順がおかしいとのこと。 (ちなみにgosqlite3に付属のcgoパッチは未適用。既に不要と思われます。)

どう考えてもcgoで解決すべき問題な気がするので Quick and Dirtyに解決パッチを作ってみました。恥ずかしながらまだgoに慣れていないので我ながら情けないコードですが。 

$GOROOT/src/cmd/cgoで以下のパッチを適用。

--- out.go.orig    2010-02-08 17:19:13.000000000 +0900
+++ out.go    2010-02-09 04:18:59.000000000 +0900
@@ -10,6 +10,7 @@
     "go/printer"
     "os"
     "strings"
+    "bytes"
 )
 
 func creat(name string) *os.File {
@@ -20,6 +21,25 @@
     return f
 }
 
+type defent_t struct {
+    def  string
+    done bool
+}
+
+func outdefs (fo *os.File, defs map[string]defent_t, name string) {
+    d := defs[name]
+    if !d.done {
+        next := d.def
+        d.done = true
+        defs[name] = d
+        _, ok := defs[next]
+        if ok && !defs[next].done {
+            outdefs(fo, defs, next)
+        }
+        fmt.Fprintf(fo, "type %s %s\n", name, d.def)
+    }
+}
+
 // writeDefs creates output files to be compiled by 6g, 6c, and gcc.
 // (The comments here say 6g and 6c but the code applies to the 8 and 5 tools too.)
 func (p *Prog) writeDefs() {
@@ -40,10 +60,19 @@
     fmt.Fprintf(fgo2, "import \"unsafe\"\n\n")
     fmt.Fprintf(fgo2, "type _ unsafe.Pointer\n\n")
 
+    var defs map[string]defent_t = make(map[string]defent_t, len(p.Typedef))
+    var bufs = bytes.NewBuffer(make([]byte, 0, 10000))
     for name, def := range p.Typedef {
-        fmt.Fprintf(fgo2, "type %s ", name)
-        printer.Fprint(fgo2, def)
-        fmt.Fprintf(fgo2, "\n")
+        bufs.Reset()
+        err := printer.Fprint(bufs, def)
+        if err != nil {
+            fatal("%s", err)
+        } else {
+            defs[name] = defent_t { bufs.String(), false }
+        }
+    }
+    for name,_ := range defs {
+        outdefs(fgo2, defs, name)
     }
     fmt.Fprintf(fgo2, "type _C_void [0]byte\n")
 

内容的には定義のテキスト表現を先に生成しておいて、前方参照がないかどうか探しているだけです。gosqlite3だけに限れば単純にgo言語の組み込みデータ型へのtypeを先に出力するだけでもコンパイルは通りますが。

ちなみにまだ試していませんが"go-db", "phf/go-sqlite3"というのがあり、こちらの方がいろいろやってくれるかもしれません。

go言語はCで書かれたライブラリへのラッパーが非常に楽に作れるみたいですね。いろいろと面白いことが出来そうです。

トラックバック

このエントリーのトラックバックURL:
http://blog.browncat.org/cgi-bin/mt/mt-tb-abc.cgi/863


コメントを投稿

(お書きになったコメントはすぐには表示されません。ご了承ください。)


About

2010年02月09日 02:28に投稿されたエントリーのページです。

ひとつ前の投稿は「macでもgo言語でX11に描画してみるメモ」です。

次の投稿は「Thunderbird3があまりに重いのでグローバル検索を止めて高速化するメモ」です。

他にも多くのエントリーがあります。メインページアーカイブページも見てください。

           

カテゴリー

Powered by
Movable Type 3.36

Twitter


最近のエントリー

デル株式会社ads

注目エントリー