5

Suppose I have a C library with code like this:

typedef int (callback_t)(int);
void register_callback(callback_t cb);

I want to write go bindings for this function and pass arbitrary go callbacks.

I found an excellent answer here. However, it is a trick that makes use of the fact that the callback accepts a void *, through which Go passes the function pointer to C and receives it back. However, this can't be applied in my example since there isn't a user void *.

The best I could do is:

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

This only works for a single register_callback (because of the global variable), but the C library can register many callbacks and invoke them all.

I hoped to achieve something like this, but this doesn't compile (put aside the clojure, it can't convert the go function to c function even though the signature is the same):

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

Is there a way to properly bind the C library?

Community
  • 1
  • 1
kaspersky
  • 3,959
  • 4
  • 33
  • 50

1 Answers1

0

You could create an array of callbacks and have the bridge iterate the array of callbacks if the there is no return value (void function).

rouzier
  • 1,160
  • 8
  • 19