2 回答

TA貢獻(xiàn)1828條經(jīng)驗(yàn) 獲得超6個贊
如果要使用第一種方法,則需要在函數(shù)調(diào)用參數(shù)之外創(chuàng)建切片,并避免臨時(shí)分配的切片頭或參數(shù)中的外部結(jié)構(gòu),因此cgo檢查不會將其視為存儲在 Go 中的指針.
b := buf.Bytes()
rc := C.the_function(unsafe.Pointer(&b[0]), C.int(buf.Len()))
該C.CString方法將更安全,因?yàn)閿?shù)據(jù)被復(fù)制到 C 緩沖區(qū)中,因此沒有指向 Go 內(nèi)存的指針,并且后面的切片bytes.Buffer不會被修改或超出范圍。您需要轉(zhuǎn)換整個字符串,而不僅僅是第一個字節(jié)。這種方法確實(shí)需要分配和復(fù)制兩次,但是如果數(shù)據(jù)量很小,與 cgo 調(diào)用本身的開銷相比,這可能不是問題。
str := buf.String()
p := unsafe.Pointer(C.CString(str))
defer C.free(p)
rc = C.the_function(p, C.int(len(str)))
如果該解決方案中不能接受數(shù)據(jù)的 2 個副本,則還有第三種選擇,您可以自己分配 C 緩沖區(qū),并將單個副本復(fù)制到該緩沖區(qū)中:
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()))
但是對于后兩種選擇,不要忘記釋放 malloc 的指針。

TA貢獻(xiàn)1725條經(jīng)驗(yàn) 獲得超8個贊
您的程序崩潰是因?yàn)樵?go1.6 中將指針傳遞給 C 的規(guī)則發(fā)生了變化(有關(guān)詳細(xì)信息,請參閱https://tip.golang.org/doc/go1.6#cgo)。
我不知道你的程序?yàn)槭裁磿罎?,所以我?chuàng)建了 Go issue https://github.com/golang/go/issues/14546。
但是不管這個問題的答案如何,我都不會使用內(nèi)部位bytes.Buffer
(就像你一樣)直接傳遞給 cgo。該bytes.Buffer
實(shí)現(xiàn)可以改變未來,你程序?qū)悠粕衩?。我只是將您需要的?shù)據(jù)復(fù)制到任何合適的結(jié)構(gòu)中,然后使用它傳遞給 cgo。
- 2 回答
- 0 關(guān)注
- 449 瀏覽
添加回答
舉報(bào)