Convert Go []byte to a C *char

前端 未结 2 654
粉色の甜心
粉色の甜心 2021-02-02 17:07

I have a byte.Buffer that I pack with data using the binary.Write() function. I then need to send this byte array to a C function. Using Go 1.6 I have not been successful at fig

2条回答
  •  终归单人心
    2021-02-02 17:48

    If you want to use your first approach, you need to create the slice outside the function call arguments, and avoid the temporarily allocated slice header or the outer structure in the arguments, so the cgo checks don't 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, in that the data is copied into a C buffer, so there is no pointer to Go memory, and there's no chance the slice behind the bytes.Buffer will be modified or go out of scope. You will want to convert the whole string, not just the first byte. This methods does need to allocate and copy twice, however if the amount of data is small it's 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 the 2 copies of the data aren't acceptable in that solution, there is a third option where you malloc the C buffer yourself, and make a single copy into that buffer:

    p := C.malloc(C.size_t(len(b)))
    defer C.free(p)
    
    // copy the data into the buffer, by converting it to a Go array
    cBuf := (*[1 << 30]byte)(p)
    copy(cBuf[:], b)
    rc = C.the_function(p, C.int(buf.Len()))
    

    But with both of those latter options, don't forget to free the malloc'ed pointer.

提交回复
热议问题