将 Go 函数作为回调传递给 C

kas*_*sky 5 c binding go cgo

假设我有一个 C 库,代码如下:

typedef int (callback_t)(int);
void register_callback(callback_t cb);
Run Code Online (Sandbox Code Playgroud)

我想为此函数编写 go 绑定并传递任意 go 回调。

我在这里找到了一个很好的答案。然而,这是一个利用回调接受 a 的事实的技巧void *,Go 通过它将函数指针传递给 C 并接收它。但是,这不能应用于我的示例,因为没有 user void *

我能做的最好的事情是:

/*
extern int gobridge(int data);

static int cbridge(void)
{
    register_callback(gobridge);
}
*/
import "C"

type Callback func (int) int

var g_cb Callback

//export gobridge
func gobridge(data C.int) C.int {
    return C.int(g_cb(int(data)))
}

func RegisterCallback(cb Callback) {
    g_cb = cb //save callback in a global
    C.cbridge()
}

func Count(left, right int) {
    C.count(C.int(left), C.int(right))
}
Run Code Online (Sandbox Code Playgroud)

这仅适用于单个 register_callback (因为全局变量),但 C 库可以注册许多回调并调用它们。

我希望实现这样的目标,但这无法编译(抛开 clojure,即使签名相同,它也无法将 go 函数转换为 c 函数):

import "C"

func RegisterCallback(cb Callback) {
    f := func (d C.int) C.int {
        return C.int(cb(int(d)))
    }
    C.register_callback(f)
}

func Count(left, right int) {
    C.count(C.int(left), C.int(right))
}
Run Code Online (Sandbox Code Playgroud)

有没有办法正确绑定C库?

rou*_*ier 0

您可以创建一个回调数组,并让桥在没有返回值(void 函数)时迭代该回调数组。