我有一些旧的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");
}
使用打包/未对齐的结构返回12而不是1 + 2 + 2 + 4 = 9。
我知道我可以创建一个字节数组并手动进行解析,但这看起来非常脆弱且容易出错......
答案 0 :(得分: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)
}
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}
答案 1 :(得分: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
然后,所有底层或第三方库正在执行一些void *或const char *并将其类型化。因此,如果可能的话,尝试将该数据转发到C层(您可以获取指针)并且根本不公开结构。
答案 2 :(得分:2)
没有办法告诉gccgo编译打包的结构。我能想到的最佳解决方案是手动添加填充:
type AlignTest struct {
c byte
_ [3]byte // anonymous padding
y int16
z int16
q int32
}
答案 3 :(得分:1)
这有效:
package main
import "unsafe"
import "fmt"
/*
struct test {
char c;
short i;
short j;
int k;
} __attribute__((packed));
*/
import "C"
type AlignTest struct {
c byte
y int16
z int16
q int32
}
func main() {
vr := new(AlignTest)
v := new(C.struct_test)
fmt.Println(unsafe.Sizeof(*vr), "\n")
fmt.Println(unsafe.Sizeof(*v), "\n")
}
输出:
12
9