如何从Go函数返回C指针?

问题描述 投票:0回答:2

我有问题是否可以从 C 上的 Go 函数指针返回?例如 main.c 可以是:

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代码:

//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)
}

cgo
命令
go build -buildmode=c-archive test.go
之后,我收到头文件并尝试通过命令
gcc -g -pthread main.c test.a -o main
将其链接到我的C项目中,所有编译和链接都成功,但在运行时我收到下一个错误:
panic: runtime error: cgo result has Go pointer
这个想法是接收指向的指针在c中的DB,做一些工作,当不需要DB时关闭DB。

c go cgo gccgo
2个回答
0
投票

正如 JimB 所说;这可能行不通(它被称为

unsafe
是有原因的)。即使您设法将指针转换为
C
可以使用的内容,也存在重大风险,因为 Go 中的垃圾收集可能会释放底层资源,因为 Go 不知道
C

中的用法

原答案

我认为

open_db
的签名应该是:
func open_db(path string) (unsafe.Pointer, error)

并且变量

db
应转换为
unsafe.Pointer
;天真地这样:
return unsafe.Pointer(db), err
但我不知道这种情况下数据库实现的细节。

您的

close_db
函数可能还需要接受
unsafe.Pointer
而不是
interface{}

参见:https://golang.org/cmd/cgo/


0
投票

如果要返回字节数据,可以返回unsafe.Pointer和字节数据大小。我使用 func C.CBytes([]byte) 它返回 unsafe.Pointer

© www.soinside.com 2019 - 2024. All rights reserved.