I'm trying to interface with a C library that uses the return values for error codes and takes in a pointer to a pointer that it sets for handles, in the C code, I would write:
handle_t *h;
int error = int create_handle(&h);
float result = do_something(h, 1, 2, 3);
handle_t
is opaque mostly, but sometimes a small struct to get state information from directly and sometimes a pointer in itself.
How do I write the go code to call this? All attempts with unsafe.Pointer and using a C.ulong tricks (to create space for the pointer to point to) haven't worked out. Also, how do I save this pointer in a struct? This was my best effort, and I can't really figure it out. I don't quite understand what go can and can't do and what it does for you w.r.t C pointers going across the FFI boundary.
type Data struct {
ptr unsafe.Pointer
}
func NewData() *Data {
handle := unsafe.Pointer{0}
err := C.create_handle(&handle)
result := C.do_something(handle, 1, 2, 3)
save := new(Data)
save.ptr = handle
return save
}
The interface to this library is out of my control and cannot be changed.
I suppose the handle_t
is a typedef of void *
. You can try the following code:
package main
/*
#include <stdio.h>
#include <stdlib.h>
typedef void* handle_t;
int create_handle(handle_t *h) {
char *p = (char*)calloc(sizeof(char), 3);
p[0] = 'a';
p[1] = 'b';
*h = p;
return 1;
}
int do_something(handle_t h, int i, int j, int k) {
char *p = (char*)h;
printf("%s\t%d
", p, i);
return 1;
}
*/
import "C"
import "unsafe"
type Data struct {
ptr C.handle_t
}
func NewData() *Data {
var handle C.handle_t = nil
C.create_handle(&handle)
C.do_something(handle, C.int(1), C.int(2), C.int(3))
return &Data{handle}
}
func main() {
data := NewData()
C.free(unsafe.Pointer(data.ptr))
}