英文:
How do I convert a Go array of strings to a C array of strings?
问题
我正在一个项目中使用cgo
,并且想要导出一个函数供使用。以下是我想要实现的示例代码:
package csplit
import (
"C"
"strings"
)
//export Split
/* Split函数接受两个C字符串作为参数,第二个字符串表示要进行分割的子字符串,然后返回一个字符串数组。示例:
Split("1,2", ",") // 返回["1", "2"]
*/
func Split(original *C.char, split *C.char) []*C.char {
goResult := strings.Split(C.GoString(original), C.GoString(split))
cResult := make([]*C.char, len(goResult))
for idx, substring := range goResult {
cResult[idx] = C.CString(substring)
}
return cResult
}
问题在于返回类型是Go分配的数据,而不是移动到C堆上。这会导致出现以下错误:runtime error: cgo result has Go pointer
。
英文:
I am using cgo
in a project, and I want to export a function for use. Here's an example of what I want to achieve:
package csplit
import (
"C"
"strings"
)
//export Split
/* The Split function takes two C strings, the second of which represents
a substring to split on, and returns an array of strings. Example:
Split("1,2", ",") // gives ["1", "2"]
*/
func Split(original *C.char, split *C.char) []*C.char {
goResult := strings.Split(C.GoString(original), C.GoString(split))
cResult := make([]*C.char, len(goResult))
for idx, substring := range goResult {
cResult[idx] = C.CString(substring)
}
return cResult
}
The problem is that the return type is Go allocated data, and not moved into the C heap. This panics with: runtime error: cgo result has Go pointer
答案1
得分: 14
你正在返回一个在Go中分配的Go切片,它与C数组是不同的结构。你需要在C中分配一个数组:
//export Split
func Split(original *C.char, split *C.char) **C.char {
goResult := strings.Split(C.GoString(original), C.GoString(split))
cArray := C.malloc(C.size_t(len(goResult)) * C.size_t(unsafe.Sizeof(uintptr(0))))
// 将C数组转换为Go数组,以便我们可以对其进行索引
a := (*[1<<30 - 1]*C.char)(cArray)
for idx, substring := range goResult {
a[idx] = C.CString(substring)
}
return (**C.char)(cArray)
}
英文:
You're returning a Go slice which is allocated in Go, and is a different structure than a C array. You need to allocate an array in C:
//export Split
func Split(original *C.char, split *C.char) **C.char {
goResult := strings.Split(C.GoString(original), C.GoString(split))
cArray := C.malloc(C.size_t(len(goResult)) * C.size_t(unsafe.Sizeof(uintptr(0))))
// convert the C array to a Go Array so we can index it
a := (*[1<<30 - 1]*C.char)(cArray)
for idx, substring := range goResult {
a[idx] = C.CString(substring)
}
return (**C.char)(cArray)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论