String slices and cgo
When working with cgo you
can convert a Go string
to a C char*
using C.Cstring
. To not leak
memory, you must C.free
the C string after use.
s := "a Go string"
cstr := C.CString(s)
// ... do something with cstr ...
C.free(unsafe.Pointer(cstr))
It’s a little more tricky to convert a Go []string
to a C char**
and get the memory management right. Here is one approach:
// cStrings converts []string to char**.
// The caller is responsible for freeing the returned char* elements
// using the returned free function.
func cStrings(elems []string) (result **C.char, free func()) {
var ret []*C.char
var frees []func()
for _, e := range elems {
cstr := C.CString(e)
ret = append(ret, cstr)
frees = append(frees, func() { C.free(unsafe.Pointer(cstr)) })
}
freeAll := func() {
for _, f := range frees {
f()
}
}
return (**C.char)(unsafe.Pointer(&ret[0])), freeAll
}
And usage looks like:
// extern void bar(char** v, int vlen);
import "C"
v := []string{"a", "b", "c", "d"}
cstrs, free := cStrings(v)
C.bar(cstrs, len(v))
free()