【问题标题】:Difficulty accessing nested C union member in go难以在 go 中访问嵌套的 C 联合成员
【发布时间】:2020-02-16 07:48:55
【问题描述】:

免责声明: 我是 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;

鉴于我可以访问 bigStruct_t 可以使用 C.bigStruct_t 访问,我在 Go 中访问/变异 member_to_access 时遇到困难。

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

机器是小端的

我尝试使用 byteArray 和 C 缓冲区,如 Golang CGo: converting union field to Go type 但不明白为什么该函数将 8 字节数组的大小作为参数。

【问题讨论】:

  • Re "不明白为什么函数的参数是8字节数组的大小。",是union的大小(其最大字段的大小)。在您的情况下,它将是 64。

标签: c go struct unions cgo


【解决方案1】:

联合可以表示为字节数组,因此该字段的权重为最大元素的大小([sizeof_union's_largest_element]byte)。 Enum 可以表示为 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))
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-12
    • 1970-01-01
    • 2013-10-17
    相关资源
    最近更新 更多