包装结构(gcc)去

Guy*_*y B 8 c gcc struct go

我有一些旧的C代码,有点大量使用压缩结构.我正在研究使用Go作为此代码的包装器,但是很难找到传递甚至为这些结构编写定义的方法.

例:

import "unsafe";

type AlignTest struct {
    c byte;
    y int16;
    z int16;
    q int32;
}

func main() {

    vr := new(AlignTest);

    fmt.Println(unsafe.Sizeof(*vr),  "\n");

}
Run Code Online (Sandbox Code Playgroud)

使用打包/未对齐的结构返回12而不是1 + 2 + 2 + 4 = 9.

我知道我可以创建一个字节数组并手动进行解析,但这看起来非常脆弱且容易出错......

pet*_*rSO 5

你可以尝试这样的事情.

package main

import (
    "encoding/binary"
    "bytes"
    "fmt"
)

type Unpacked struct {
    C byte
    Y int16
    Z int16
    Q int32
}

type Packed struct {
    B [9]byte
}

func main() {
    var u Unpacked
    var p Packed
    var buf = bytes.NewBuffer(make([]byte, 0, len(p.B)))
    // Unpacked to Packed 
    u = Unpacked{1, 2, 3, 4}
    if err := binary.Write(buf, binary.BigEndian, &u); err != nil {
        fmt.Println(err)
    }
    if err := binary.Read(buf, binary.BigEndian, &p); err != nil {
        fmt.Println(err)
    }
    fmt.Println("u", u, "to", "p", p)
    // Packed to Unpacked
    p = Packed{[...]byte{1, 2, 3, 4, 5, 6, 7, 8, 9}}
    if err := binary.Write(buf, binary.BigEndian, &p); err != nil {
        fmt.Println(err)
    }
    if err := binary.Read(buf, binary.BigEndian, &u); err != nil {
        fmt.Println(err)
    }
    fmt.Println("p", p, "to", "u", u)
}
Run Code Online (Sandbox Code Playgroud)

.

Output:
u {1 2 3 4} to p {[1 0 2 0 3 0 0 0 4]}
p {[1 2 3 4 5 6 7 8 9]} to u {1 515 1029 101124105}
Run Code Online (Sandbox Code Playgroud)


小智 5

您可能想要重新考虑您的体系结构 - 尝试将二进制输入传递到C层并使用现有结构(您不会破坏您不更改的内容).我假设结构包装看起来像这样:

#ifdef WINDOWS
#pragma pack(push)
#endif
#pragma pack(BYTEALIGNMENT) // e.g. "#pragma pack(1)" or "#pragma pack(8)"

//--- Some packed structs

#ifdef WINDOWS
#pragma pack(pop)
#endif
#ifdef POSIX
#pragma pack()
#endif
Run Code Online (Sandbox Code Playgroud)

所有底层或第三方库正在做的是采取一些void*或const char*并将其类型化.因此,如果可能的话,尝试将该数据转发到C层(您可以获取指针)并且根本不暴露结构.


Eva*_*haw 2

没有办法告诉 gccgo 编译打包结构。我能想到的最好的解决方案是手动添加填充:

type AlignTest struct {
    c byte
    _ [3]byte // anonymous padding
    y int16
    z int16
    q int32
}
Run Code Online (Sandbox Code Playgroud)