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

标签 c go cgo gccgo

我有疑问是否可以从 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 将它链接到我的 c 项目中-g -pthread main.c test.a -o main,所有编译和链接都成功,但在运行时我收到下一个错误:panic: runtime error: cgo result has Go pointer 这个想法在 c 中接收指向 DB 的指针,做一些工作,当不需要 DB 时关闭 DB。

最佳答案

正如 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/

关于c - 如何从 Go 函数返回 C 指针?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46591758/

相关文章:

c - 如何将两个文本文件读入两个动态分配的数组并在c中逐字节比较它们?

从内核模块更改 gnome 背景

c - 如何在共享内存中存储变量

pointers - 如何将指针分配给 Go map

c - 如何将 Go 绑定(bind)建模为使用 union 的 C 结构?

c - 如何将Golang的cgo与链接到math.h的C库一起使用?

c - 海湾合作委员会/Linux : hook exit() call to prevent exit from happening

go - 通过进口商获取有关包裹的所有信息并反射(reflect)?

go - 标志重新定义 - 在 YouTube 数据 API 3 中按键 panic 搜索

macos - 使用 golang 进行 Mac 交叉编译(或替代方案)