如何在go中将[] [] byte转换为**char

Joh*_*ore 5 type-conversion go cgo

我想从go [] []字节转换为C**char.换句话说,我有一个字节矩阵,我想转换为C中的char双指针.

请假设我必须有一个[] []字节作为输入,**char作为输出.

我知道可以通过执行以下操作从[] byte转换为*char:

((*C.char)(unsafe.Pointer(&data[0])))
Run Code Online (Sandbox Code Playgroud)

但似乎不可能将这种情况扩展到第二个维度.我尝试了一些非常复杂的东西,我将[] []字节打包成一个新的[]字节.然后我将该[]字节发送到C函数,该函数使用指针算法创建一个**char,指向正确位置的新[]字节.

然而,这种转换给了我奇怪的行为,我的数据在几次迭代中是正确的,但在函数调用之间似乎被破坏了.

如果有人有任何想法,我会非常感激.

从响应中我看到,说明我正在处理原始数据而不是字符串也很重要.因此go字节类型.因此,如果添加了C字符串终止符,原始数据将被破坏.我只是使用C**char,因为char的大小是一个字节.这就是说,谢谢你们的回应.我能够根据自己的需要调整接受的答案.

jim*_*imt 3

这必须手动完成。您必须分配一个新**C.char类型并循环遍历切片中的每个元素[][]byte以将其分配给新列表。这涉及**C.char到每次迭代时将指针偏移正确的大小。

这是执行此操作的示例程序。

正如下面的注释所建议的,如果您打算char *使用类似于printfC 中的内容来打印列表,请确保输入字符串以 NULL 结尾。理想情况下,通过使用C.CString()函数转换它们。但这假设它们被视为字符串。否则,您可能还需要提供一种将每个单独列表的长度传递char *给 C 函数的方法。

package main

/*
#include <stdlib.h>
#include <stdio.h>

void test(char **list, size_t len)
{
    size_t i;

    for (i = 0; i < len; i++) {
        //printf("%ld: %s\n", i, list[i]);
    }
}
*/
import "C"
import "unsafe"

func main() {
    list := [][]byte{
        []byte("foo"),
        []byte("bar"),
        []byte("baz"),
    }

    test(list)
}

func test(list [][]byte) {
    // Determine the size of a pointer on the current system.
    var b *C.char
    ptrSize := unsafe.Sizeof(b)

    // Allocate the char** list.
    ptr := C.malloc(C.size_t(len(list)) * C.size_t(ptrSize))
    defer C.free(ptr)

    // Assign each byte slice to its appropriate offset.
    for i := 0; i < len(list); i++ {
        element := (**C.char)(unsafe.Pointer(uintptr(ptr) + uintptr(i)*ptrSize))
        *element = (*C.char)(unsafe.Pointer(&list[i][0]))
    }

    // Call our C function.
    C.test((**C.char)(ptr), C.size_t(len(list)))
}
Run Code Online (Sandbox Code Playgroud)

输出如下:

$ go run charlist.go 
0: foo
1: bar
2: baz
Run Code Online (Sandbox Code Playgroud)