Littleroot Blog

Cgo: convert []string to char**

When using 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 some_func(char** v, int vlen);
import "C"

func someFunc(v []string) {
    cstrs, free := cStrings(v)
    defer free()
    C.some_func(cstrs, len(v))
}