如何将Go字符串数组转换为C字符串数组?

huangapple go评论124阅读模式
英文:

How do I convert a Go array of strings to a C array of strings?

问题

我正在一个项目中使用cgo,并且想要导出一个函数供使用。以下是我想要实现的示例代码:

  1. package csplit
  2. import (
  3. "C"
  4. "strings"
  5. )
  6. //export Split
  7. /* Split函数接受两个C字符串作为参数,第二个字符串表示要进行分割的子字符串,然后返回一个字符串数组。示例:
  8. Split("1,2", ",") // 返回["1", "2"]
  9. */
  10. func Split(original *C.char, split *C.char) []*C.char {
  11. goResult := strings.Split(C.GoString(original), C.GoString(split))
  12. cResult := make([]*C.char, len(goResult))
  13. for idx, substring := range goResult {
  14. cResult[idx] = C.CString(substring)
  15. }
  16. return cResult
  17. }

问题在于返回类型是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:

  1. package csplit
  2. import (
  3. "C"
  4. "strings"
  5. )
  6. //export Split
  7. /* The Split function takes two C strings, the second of which represents
  8. a substring to split on, and returns an array of strings. Example:
  9. Split("1,2", ",") // gives ["1", "2"]
  10. */
  11. func Split(original *C.char, split *C.char) []*C.char {
  12. goResult := strings.Split(C.GoString(original), C.GoString(split))
  13. cResult := make([]*C.char, len(goResult))
  14. for idx, substring := range goResult {
  15. cResult[idx] = C.CString(substring)
  16. }
  17. return cResult
  18. }

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中分配一个数组:

  1. //export Split
  2. func Split(original *C.char, split *C.char) **C.char {
  3. goResult := strings.Split(C.GoString(original), C.GoString(split))
  4. cArray := C.malloc(C.size_t(len(goResult)) * C.size_t(unsafe.Sizeof(uintptr(0))))
  5. // 将C数组转换为Go数组,以便我们可以对其进行索引
  6. a := (*[1<<30 - 1]*C.char)(cArray)
  7. for idx, substring := range goResult {
  8. a[idx] = C.CString(substring)
  9. }
  10. return (**C.char)(cArray)
  11. }
英文:

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:

  1. //export Split
  2. func Split(original *C.char, split *C.char) **C.char {
  3. goResult := strings.Split(C.GoString(original), C.GoString(split))
  4. cArray := C.malloc(C.size_t(len(goResult)) * C.size_t(unsafe.Sizeof(uintptr(0))))
  5. // convert the C array to a Go Array so we can index it
  6. a := (*[1&lt;&lt;30 - 1]*C.char)(cArray)
  7. for idx, substring := range goResult {
  8. a[idx] = C.CString(substring)
  9. }
  10. return (**C.char)(cArray)
  11. }

huangapple
  • 本文由 发表于 2017年1月6日 02:24:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/41492071.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定