返回信息流【不知道这个系列能出多少集。。。】
已经在SO上问过了:http://stackoverflow.com/questions/38027473/python-ctype-pack-vs-g-pragma-pack
懒得翻译了,渣英语,大家懂的。。。
I intent to serialize a struct like this to a "compacted" binary:
#include <cstdio>
#include <iostream>
using namespace std;
#define print(x) cout << x << endl
#pragma pack(1)
class Foo {
uint32_t a: 1;
uint32_t b: 2;
uint32_t c: 5;
uint64_t d;
};
int main() {
print(sizeof(char));
print(sizeof(Foo));
return 0;
};
It works well here, the size of class "Foo" is 9, which is exactly what I want.
But when I try to re-implement this with Python ctypes lib, everything goes wrong.
import ctypes
from io import BytesIO
from ctypes import *
from binascii import hexlify
class RawMessage(ctypes.Structure):
_pack_ = 1
_fields_ = [
('a', ctypes.c_uint, 1),
('b', ctypes.c_uint, 2),
('c', ctypes.c_uint, 5),
('d', ctypes.c_ulong),
]
def dump(o):
s = BytesIO()
s.write(o)
s.seek(0)
return hexlify(s.read())
if __name__ == '__main__':
m = RawMessage()
m.a = m.b = m.c = m.d = 0xFFFFFFFFFFFFFFFF
print ctypes.sizeof(m)
print dump(m)
The size of the RawMessage is 12. I guess the "_pack_" property doesn't work at all. The binary representation of the message m is "ff000000ffffffffffffffff".
It's a confusing problem. Please help me with that.
Thanks.
这是一条镜像帖。来源:北邮人论坛 / python / #14673同步于 2016/6/25
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Python机器人发帖
[问题]果然双被Python坑了
Wizmann
2016/6/25镜像同步5 回复
订阅后,新回复会通过你的通知中心匿名送达。
5 条回复
楼主被C语言和Python语言一起坑了。
语言之间的交互,看的是ABI(application binary interface)。但C语言设计的时候就把binary interface抛到语言外边了。所以,C语言struct的layout什么的,是由平台的ABI决定的。比如AMD64 SysV ABI。C++的class也是。class里的field、vtable什么的,也是abi规定的,而不是语言。
所以……楼主啊,你遇到大麻烦了(摸摸头)。如果你在意程序之间的二进制交互,就不要用bit-fields,不要用自定义的alignment。如果是message的话,最好手动序列化。把struct/class转换成unsigned char*,对于C/C++来说,确实规定了这样转换的结果是得到这个对象的object representation(就是按字节序列的表示),但这种表示方法是实现相关的(由ABI规定)。
引用 https://docs.python.org/3.5/library/ctypes.html :
Warning
ctypes does not support passing unions or structures with bit-fields to functions by value. While this may work on 32-bit x86, it’s not guaranteed by the library to work in the general case. Unions and structures with bit-fields should always be passed to functions by pointer.
nonono。。。
我并没想踩ABI那边的雷。。。
我只是想做一个“紧凑”的二进制。。。ctypes不是方便嘛。。。
【 在 nuanyangyang 的大作中提到: 】
: 楼主被C语言和Python语言一起坑了。
: 语言之间的交互,看的是ABI(application binary interface)。但C语言设计的时候就把binary interface抛到语言外边了。所以,C语言struct的layout什么的,是由平台的ABI决定的。比如AMD64 SysV ABI。C++的class也是。class里的field、vtable什么的,也是abi规定的,而不是语言。
: 所以……楼主啊,你遇到大麻烦了(摸摸头)。如果你在意程序之间的二进制交互,就不要用bit-fields,不要用自定义的alignment。如果是message的话,最好手动序列化。把struct/class转换成unsigned char*,对于C/C++来说,确实规定了这样转换的结果是得到这个对象的object representation(就是按字节序列的表示),但这种表示方法是实现相关的(由ABI规定)。
: ...................
【 在 Wizmann 的大作中提到: 】
: nonono。。。
: 我并没想踩ABI那边的雷。。。
: 我只是想做一个“紧凑”的二进制。。。ctypes不是方便嘛。。。
: ...................
当你说”紧凑“这个词的时候,就已经暗示了layout,就暗示了从C++的struct的高级语言到bytes/size/alignment的低级实现的映射,就涉及了ABI的领域。所以,不好意思,你已经踩雷了。
i fxxked a dog...
=。=
【 在 nuanyangyang 的大作中提到: 】
:
: 当你说”紧凑“这个词的时候,就已经暗示了layout,就暗示了从C++的struct的高级语言到bytes/size/alignment的低级实现的映射,就涉及了ABI的领域。所以,不好意思,你已经踩雷了。
狗表示压力很大
【 在 aquamarine 的大作中提到: 】
: 用bitstruct解决了。。。
: 本来真的是想DRY的。。。结果发现处处日狗。。。疯了
: