如何在go中将[] [] byte转换为** char [英] How to convert from [][]byte to **char in go

查看:41
本文介绍了如何在go中将[] [] byte转换为** char的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I would like to convert from a go [][]byte to a C **char. In other words, I have a byte matrix in go that I would like to convert to a char double pointer in C.

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

Please assume that I HAVE to have a [][]byte as input and a **char as output.

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

I know it is possible to convert from []byte to *char by doing something like:

((*C.char)(unsafe.Pointer(&data[0])))

但是似乎无法将这种情况扩展到第二维.我尝试了一些非常精细的操作,在其中将[] []字节打包到一个新的[] byte中.然后,我将该[]字节发送到C函数,该函数使用指针算法创建一个** char,以在正确的位置指向新的[]字节.

But it does not seem possible to extend this case into the second dimension. I have tried something pretty elaborate, where I pack a [][]byte into a new []byte. I then send that []byte to a C function that creates a **char using pointer arithmetic to point into the new []byte at the correct locations.

这种转换给我带来了奇怪的行为,即我的数据经过几次迭代是正确的,但似乎在两次函数调用之间被破坏了.

This conversion is giving me strange behaviour though, where my data would be correct for a few iterations, but gets corrupted seemingly between function calls.

如果有人有任何想法,我将不胜感激.

If anyone has any ideas, I would really appreciate it.

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

From the responses I see it is also important to state that I'm working with raw data and not strings. Hence the go byte type. The original data would, therefore, be corrupted if C string terminators are added. I'm just using C **char, because a char is one byte in size. That said, thanks for the responses. I was able to adapt the accepted answer for my needs.

推荐答案

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

This has to be done manually. You have to allocate a new **C.char type and loop through each element in the [][]byte slice to assign it to the new list. This involves offsetting the **C.char pointer by the correct size for each iteration.

这是一个执行此操作的示例程序.

Here is an example program which does this.

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

As the comments below suggest, if you intend to print the char * lists using something like printf in C, then ensure the input strings are NULL terminated. Ideally by converting them using the C.CString() function. This assumes that they are to be treated as strings though. Otherwise you may also need to supply a way to pass the length of each individual char * list to the C function.

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

这篇关于如何在go中将[] [] byte转换为** char的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆