【问题标题】:How do I convert a Go array of strings to a C array of strings?如何将 Go 字符串数组转换为 C 字符串数组?
【发布时间】:2017-05-20 09:52:50
【问题描述】:

我在一个项目中使用cgo,我想导出一个函数以供使用。这是我想要实现的示例:

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
}

问题是返回类型是 Go 分配的数据,而不是移动到 C 堆中。这会引起恐慌:runtime error: cgo result has Go pointer

【问题讨论】:

    标签: c arrays string go cgo


    【解决方案1】:

    您正在返回一个 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))))
    
        // 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)
    }
    

    【讨论】:

    • 啊,谢谢。我相信首先分配 C 数组可能是诀窍。 (一旦我为我的用例测试它就会接受,或者在必要时向问题添加更多细节)
    • @haiqus: 抱歉,我打错了,应该在 malloc 中包含 sizeof (我在想 char 而不是 char*,如果我没有省略了 sizeof)。我对其进行了修改以显示正确的 malloc 大小。
    • 我迟到了,但(*[1&lt;&lt;30 - 1]*C.char) 是什么意思?
    猜你喜欢
    • 1970-01-01
    • 2016-11-20
    • 2020-05-28
    • 2021-12-13
    • 1970-01-01
    • 2017-11-27
    • 1970-01-01
    相关资源
    最近更新 更多