首页 > 解决方案 > 难以在 go 中访问嵌套的 C 联合成员

问题描述

免责声明:我是 Go/CGo 的新手。

我正在 64 位平台上使用这个 C 结构,试图访问联合的 uint32 成员

typedef enum {
    n = 0,
    ix = 1,
    iy = 3 
} enum_x;

struct smallStruct_s {
     union {
        uint32 a[4];
        uint32 b[8];
        uint32 c[16];
    } u;
} smallStruct_t;

struct bigStruct_s {
   enum_x fa;
   union {
        uint32 member_to_access; <<<<<< This is member that needs to be accessed
        smallStruct_t an;
   } un_t;
} bigStruct_t;

member_to_access鉴于我可以bigStruct_t使用C.bigStruct_t.

如何unsafe.Pointer在不违反任何内存限制的情况下将 member_to_access 的地址传递给在 C 中接受 void* 的函数。

机器是小端

我尝试使用 Golang CGo 中提到的 byteArray 和 C 缓冲区 :将联合字段转换为 Go 类型 ,但不明白为什么该函数将 8 字节数组的大小作为参数。

标签: cgostructunionscgo

解决方案


联合可以表示为字节数组,因此该字段的权重为最大元素的大小([sizeof_union's_largest_element]byte)。枚举可以表示为 int。

我建议为此使用偏移量:

type bigStruct struct {
    instance unsafe.Pointer
}

func (bs *bigStruct) fa() int {
    return int(*(*C.int)(bs.instance))
}

func (bs *bigStruct) memberToAccess() uint32 {
    // C.sizeof_int refers to sizeof(enum_x)
    return uint32(*(*C.uint32_t)(unsafe.Pointer(uintptr(bs.instance) + C.sizeof_int)))
}

func (bs *bigStruct) an() *C.smallStruct_t {
    return (*C.smallStruct_t)(unsafe.Pointer(uintptr(bs.instance) + C.sizeof_int))
}

func (bs *bigStruct) an_u() []byte {
    // cgo having same thought about and takes smallStruct_t.u as array
    return (*C.smallStruct_t)(unsafe.Pointer(uintptr(bs.instance) + C.sizeof_int)).u[:]
}

func (bs *bigStruct) next_field_after_un_t() *Type {
    return (*Type)(unsafe.Pointer(uintptr(bs.instance) + C.sizeof_int + C.sizeof_smallStruct_t))
}

推荐阅读