Best way to pass a string to a C function

107 views
Skip to first unread message

David Butler (Cro)

unread,
Mar 22, 2026, 4:44:51 AM (yesterday) Mar 22
to golang-nuts
Hello all

So, if you look up documentation on CGO, in general, you will find that this is the convention that you should use if you want to call a C function and pass a string that will not be retained:

cStr := C.CString(goStr)
defer C.free(unsafe.Pointer(cStr))
C.SomeCFunction(cStr)

If you are doing this a lot, like for example specifying a bunch of configuration options, all the overhead of converting the string can get really distracting.  In my opinion, I think something like this would be ideal:

func toCString(s string) *C.char {
buf := append([]byte(s), 0)
return (*C.char)(unsafe.Pointer(&buf[0]))
}

C.SomeCFunction(toCstring(goStr))

Manually creating the C string with null terminator, and using unsafe.Pointer seems to work alright, and is really convenient to use.

So the question is, am I missing some critical flaw, or I'm just tricking myself into thinking this is safe(ish)?  If not, then why is the defer C.free(unsafe.Pointer(cStr)) patter prescribed so commonly?

Thanks :) 

Ian Lance Taylor

unread,
Mar 22, 2026, 5:08:41 AM (yesterday) Mar 22
to David Butler (Cro), golang-nuts
Your approach seems safe to me. One risk would be if somebody looking
at this code doesn't realize that toCString is only safe to use if the
C function does not retain the string. That is obvious on the page
with the usual C.CString/C.free approach. It is much less obvious with
toCString.

Ian

David Butler (Cro)

unread,
8:33 AM (10 hours ago) 8:33 AM
to golang-nuts
Yeah, good point, I suppose I'm optimizing for an edge case use... 

A better name would be toNonRetainedCString

Reply all
Reply to author
Forward
0 new messages