C++ 如何在cgo中处理压缩结构中的char*?

C++ 如何在cgo中处理压缩结构中的char*?,c++,c,go,struct,cgo,C++,C,Go,Struct,Cgo,由于Go不支持packed struct,我发现这篇很棒的文章用示例解释了如何在Go中使用packed struct 问题是当我尝试用char*代替[10]char时,它不起作用。我不确定这种转换如何使用[10]字符,而不是char*。下面是取自上述文章并用char*修改的示例代码 主程序包 /* #包括“stdio.h” #布拉格语包(1) 类型定义结构{ 无符号字符a; 字符b; INTC; 无符号整数d; char*e;//从char[10]更改为char* }包装; 无效印刷包装(包装p

由于Go不支持packed struct,我发现这篇很棒的文章用示例解释了如何在Go中使用packed struct

问题是当我尝试用char*代替[10]char时,它不起作用。我不确定这种转换如何使用[10]字符,而不是char*。下面是取自上述文章并用char*修改的示例代码

主程序包
/*
#包括“stdio.h”
#布拉格语包(1)
类型定义结构{
无符号字符a;
字符b;
INTC;
无符号整数d;
char*e;//从char[10]更改为char*
}包装;
无效印刷包装(包装p){
printf(“\n来自C\na:%d\nb:%d\nc:%d\nd:%d\ne:%s\n”,p.a、p.b、p.C、p.d、p.e);
}
*/
输入“C”
进口(
“字节”
“编码/二进制”
)
//GoPack是c压缩结构的go版本
类型GoPack结构{
a单元8
b国际8
c int32
d uint32
e[10]uint8
}
//Pack生成go结构的打包版本
func(g*GoPack)包装(外包装*C.包装){
buf:=&bytes.Buffer{}
binary.Write(buf,binary.LittleEndian,g)
*out=*(*C.packed)(C.CBytes(buf.Bytes()))
}
func main(){
pack:=&GoPack{1,2,3,4,[10]字节{}
副本(包装e[:],“TEST123”)
cpack:=C.packed{}//只是为了分配内存,仍然在GC控制下
pack.pack(&cpack)
C.印刷包装(cpack)
}
我是第一次使用cgo,所以如果我在任何时候出错,请纠正我。

您正在将十(零)个字节的
GoPack.e
写入
packed.e
类型的
char*
。这不起作用,因为指针将是4或8个字节,具体取决于您的系统,因此即使这些字节表示有效指针,您也会溢出分配的内存量

如果你想用一个有效的
packed.e
字段创建一个有效的结构,你需要在C堆中分配10字节的内存,将字节复制到该堆中,然后将
packed.e
指向这个分配的内存。(在释放相应的
packed
结构时,还需要释放此内存)。您不能直接使用
二进制文件执行此操作。请编写

您可以以此为起点:

buf := &bytes.Buffer{}
binary.Write(buf, binary.LittleEndian, g.a)
binary.Write(buf, binary.LittleEndian, g.b)
binary.Write(buf, binary.LittleEndian, g.c)
binary.Write(buf, binary.LittleEndian, g.d)
binary.Write(buf, binary.LittleEndian, uintptr(C.CBytes(g.e))
*out = *(*C.packed)(C.CBytes(buf.Bytes()))
函数
C.CBytes(b)
在C堆中分配
len(b)
字节,并将
b
中的字节复制到其中,返回一个
不安全的.Pointer

请注意,我已经从代码中复制了您的
*out=*(*C.packed).
行。这实际上会导致内存泄漏和不必要的拷贝。可能最好使用一个writer将字节直接写入
out
指向的内存

也许是这个

const N = 10000 // should be sizeof(*out) or larger
buf := bytes.NewBuffer((*[N]byte)(unsafe.Pointer(out))[:])
这将生成一个
bytes.Buffer
,它直接写入
out
结构,而不需要经过任何中间内存。请注意,由于不安全的诡计,如果您写入的数据字节数超过
out
所指出的字节数,则很容易发生缓冲区溢出


警告:这一切都非常糟糕,并且容易出现与C中相同的问题,您需要检查cgo指针规则以确保不易受到垃圾收集交互的攻击。一点建议:如果您说“在指针和内存分配方面没有太多经验”,您可能应该避免编写或包含这样的代码,因为它可能带来的问题是邪恶的,可能不会立即显现出来。

您能举个例子吗?这会有帮助的。我在指针和内存分配方面没有太多经验。谢谢你的明确解释。通过几个小时的绞尽脑汁,我终于明白了我的意思,就像你解释的那样(存储指针位置而不是字符数组)。嘿@Abhibalgami,你愿意分享你的最终解决方案吗?@Mike是的,正如我在之前的评论中所说,我的答案与公认的答案完全相同。我存储了指针的位置,稍后cgo将能够访问该位置