If you want to use your first approach, you need to create a slice outside the arguments of the function call and avoid temporarily highlighting the slice header or external structure in the arguments, so cgo
checks cgo
not see it as a pointer stored in Go.
b := buf.Bytes() rc := C.the_function(unsafe.Pointer(&b[0]), C.int(buf.Len()))
The C.CString
method will be safer since the data will be copied to the C buffer, so there is no pointer to Go memory, and there is no way for the bytes.Buffer
slice to be changed or out of volume. You will want to convert the entire string, not just the first byte. These methods need to be selected and copied twice, however, if the amount of data is small, this is probably not a concern compared to the overhead of the cgo call itself.
str := buf.String() p := unsafe.Pointer(C.CString(str)) defer C.free(p) rc = C.the_function(p, C.int(len(str)))
If 2 copies of data are unacceptable in this solution, there is a third option when you yourself create a C buffer and make one copy in this buffer:
p := C.malloc(C.size_t(len(b))) defer C.free(p)
But with both of these last options, don't forget to free the malloc'ed pointer.
source share