I have question is it possible to return from Go function pointer on C? For example main.c can be:
struct open_db_return db_ptr = open_db(db_path);
GoSlice backet = {"DB", 2, 2};
GoSlice key = {"CONFIG", 6, 6};
struct get_value_return val = get_value(db_ptr.r0, backet, key);
close_db(db_ptr.r0);
Go code is next:
//export open_db
func open_db(path string) (interface{}, error) {
db, err := db.Open(path, 0600, nil)
if err != nil {
return nil, err
}
return db, nil
}
//export close_db
func close_db(db interface{}) {
ldb := db.(*db.DB)
ldb.Close()
}
//export get_value
func get_value(db interface{}, backet_name []byte, key_name []byte) ([]byte, error) {
ldb := db.(*db.DB)
var value []byte
fn := func(tx *db.Tx) error {
value = tx.Bucket(backet_name).Get(key_name)
return nil
}
return value, ldb.View(fn)
}
After cgo
command go build -buildmode=c-archive test.go
i receive header file and trying to link it into my c project via command gcc -g -pthread main.c test.a -o main
, all compiled and linked succsesful but in runtime i receive next error: panic: runtime error: cgo result has Go pointer
The idea is receive pointer to DB in c, do some work and when DB not needed close DB.
As JimB says; this probably won't work (it's called unsafe
for a reason). Even if you manage to cast the pointer to something that is consumable by C
, there is major risk because of the garbage collection in Go potentially freeing the underlying resources because Go doesn't know about the usages in C
I think the signature for open_db
should be: func open_db(path string) (unsafe.Pointer, error)
And the variable db
should be converted to unsafe.Pointer
; naively like this: return unsafe.Pointer(db), err
but I don't know the specifics of the database implementation in this case.
Your close_db
function will probably also need to accept an unsafe.Pointer
instead of an interface{}