i'm using cgo for developing library binding from Go. Let me consider the C struct and Go Struct as below.
struct cons_t {
size_t type;
cons_t *car;
cons_t *cdr;
};
cons_t* parse(const char *str);
and this is go's struct
type Cons struct {
type int;
car *Cons;
cdr *Cons;
}
For implementing Go function as below, what is better way to implement TranslateCCons2GoCons?
func Parse (str string) *Cons {
str_ptr := C.CString(string);
cons_ptr := C.parse(str_ptr);
retCons := TranslateCCons2GoCons(cons_ptr);
return retCons;
}
My first answer is as below.
/*#cgo
int getType(cons_t *cons) {
return cons->type;
}
cons_t *getCar(cons_t *cons) {
return cons->car;
}
cons_t *getCdr(cons_t *cons) {
return cons->cdr;
}
*/
func TranslateCCons2GoCons (c *C.cons_t) Cons {
type := C.getType(c);
car := C.getCar(c);
cdr := C.getCdr(c);
// drop null termination for simplicity
return Cons{type, TranslateCCons2GoCons(car), TranslateCCons2GoCons(cdr)};
}
are there any better way?
I would recommend against the accessor functions. You should be able to access the fields of the C struct directly, which will avoid the Go -> C function call overhead (which is non-trivial). So you might use something like:
func TranslateCCons2GoCons (c *C.cons_t) *Cons {
if c == nil {
return nil
}
return &Cons{
type: int(c.type),
car: TranslateCCons2GoCons(c.car),
cdr: TranslateCCons2GoCons(c.cdr),
}
}
Also, if you allocate a C string with C.CString
, you need to free it. So your Parse
function should look something like:
func Parse (str string) *Cons {
str_ptr := C.CString(str)
defer C.free(unsafe.Pointer(str_ptr)
cons_ptr := C.parse(str_ptr)
retCons := TranslateCCons2GoCons(cons_ptr)
// FIXME: Do something to free cons_ptr here. The Go runtime won't do it for you
return retCons
}