我想从go [] []字节转换为C ** char。换句话说,我有一个字节矩阵,我想转换为C中的char双指针。
请假设我必须将[] []字节作为输入并将** char作为输出。
我知道可以通过执行以下操作从[] byte转换为* char:
((*C.char)(unsafe.Pointer(&data[0])))
但似乎无法将此案例扩展到第二维度。我尝试了一些非常复杂的东西,我将[] []字节打包成一个新的[]字节。然后我将该[]字节发送到C函数,该函数使用指针算法创建一个** char,指向正确位置的新[]字节。
然而,这种转换给了我奇怪的行为,我的数据在几次迭代中是正确的,但在函数调用之间似乎被破坏了。
如果有人有任何想法,我会非常感激。
从回复中我看到说明我正在使用原始数据而不是字符串也很重要。因此go字节类型。因此,如果添加了C字符串终止符,原始数据将被破坏。我只是使用C ** char,因为char的大小是一个字节。这就是说,谢谢你的回应。我能够根据自己的需要调整已接受的答案。
答案 0 :(得分:4)
未经测试的骨架:
func foo(b [][]byte) {
outer := make([]*C.char, len(b)+1)
for i, inner := range b {
outer[i] = C.CString(string(inner))
}
C.bar(unsafe.Pointer(&outer[0])) // void bar(**char) {...}
}
编辑:完整示例(已测试):
package main
/*
#include <stdlib.h>
#include <stdio.h>
void bar(char **a) {
char *s ;
for (;(s = *a++);)
printf("\"%s\"\n", s);
}
*/
import "C"
import "unsafe"
func foo(b [][]byte) {
outer := make([]*C.char, len(b)+1)
for i, inner := range b {
outer[i] = C.CString(string(inner))
}
C.bar((**C.char)(unsafe.Pointer(&outer[0]))) // void bar(**char) {...}
}
func main() {
foo([][]byte{[]byte("Hello"), []byte("world")})
}
(15:24) jnml@fsc-r550:~/src/tmp/SO/14833531$ go run main.go
"Hello"
"world"
(15:25) jnml@fsc-r550:~/src/tmp/SO/14833531$
答案 1 :(得分:3)
这必须手动完成。您必须分配新的**C.char
类型并循环遍历[][]byte
切片中的每个元素,以将其分配给新列表。这涉及将**C.char
指针偏移每次迭代的正确大小。
这是一个执行此操作的示例程序。
如下面的评论所示,如果您打算在C中使用char *
之类的内容打印printf
列表,请确保输入字符串为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)))
}
输出如下:
$ go run charlist.go
0: foo
1: bar
2: baz