以下のパッチは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で書かれたライブラリへのラッパーが非常に楽に作れるみたいですね。いろいろと面白いことが出来そうです。