这是this question的后续行动。我在那里假设可能不是真的,这就是我明确询问它的原因。因为我忘了询问这是否真的可行,我已经就此提出了issue #8114。
使用cgo,Go代码可以在C类型上运行,如下所示:
package foo
//#include <sys/stat.h>
import "C"
func fileSizeFromStat(stat *C.struct_stat) int64 {
return int64(stat.st_size)
}
反过来可能吗?即编写在go类型上运行的C函数?上述问题概述了具体内容;我想编组无法从Go代码访问的C结构,因为它们使用了联合或位域,或者因为它们的对齐使它们与Go代码不兼容。
答案 0 :(得分:1)
据我所知,不,你不能。
但是你可以使用像https://github.com/OneOfOne/go-nfqueue/blob/master/nfqueue.go#L130这样丑陋的东西,你可以导出一个Go函数,它需要很多指针并在go中构造你的Go结构。
答案 1 :(得分:1)
我编写了以下肮脏的黑客来解决明显无法从C访问Go结构。虽然这个hack不能保证工作,但它适用于Go和C同意如何布局结构的情况对我感兴趣的所有案件都是如此。
对于我想要访问的每个Go结构
type JewelTarget struct {
SensRes [2]byte
Id [4]byte
Baud int
}
我创建了一个相应的C结构,它具有相同宽度的字段,并且希望具有相同的布局:
typedef ptrdiff_t GoInt;
struct JewelTarget {
uint8_t SensRes[2];
uint8_t Id[4];
GoInt Baud;
};
然后我编写使用这些C结构的C函数:
extern void
marshallJewelTarget(nfc_target *nt, const struct JewelTarget *jt)
{
nfc_jewel_info *ji = &nt->nti.nji;
memcpy(ji->btSensRes, jt->SensRes, sizeof(jt->SensRes));
memcpy(ji->btId, jt->Id, sizeof(jt->Id));
nt->nm.nbr = jt->Baud;
nt->nm.nmt = NMT_JEWEL;
}
并将它们称为参数具有相应的Go类型:
func (d *JewelTarget) Marshall() uintptr {
nt := mallocTarget()
jt := (*C.struct_JewelTarget)(unsafe.Pointer(d))
C.marshallJewelTarget(nt, jt)
return uintptr(unsafe.Pointer(nt))
}
所有示例均来自我的nfc bindings。