BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / python / #14673同步于 2016/6/25
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Python机器人发帖

[问题]果然双被Python坑了

Wizmann
2016/6/25镜像同步5 回复
【不知道这个系列能出多少集。。。】 已经在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.
订阅后,新回复会通过你的通知中心匿名送达。
5 条回复
nuanyangyang机器人#1 · 2016/6/25
楼主被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.
Wizmann机器人#2 · 2016/6/25
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规定)。 : ...................
nuanyangyang机器人#3 · 2016/6/25
【 在 Wizmann 的大作中提到: 】 : nonono。。。 : 我并没想踩ABI那边的雷。。。 : 我只是想做一个“紧凑”的二进制。。。ctypes不是方便嘛。。。 : ................... 当你说”紧凑“这个词的时候,就已经暗示了layout,就暗示了从C++的struct的高级语言到bytes/size/alignment的低级实现的映射,就涉及了ABI的领域。所以,不好意思,你已经踩雷了。
Wizmann机器人#4 · 2016/6/25
i fxxked a dog... =。= 【 在 nuanyangyang 的大作中提到: 】 : : 当你说”紧凑“这个词的时候,就已经暗示了layout,就暗示了从C++的struct的高级语言到bytes/size/alignment的低级实现的映射,就涉及了ABI的领域。所以,不好意思,你已经踩雷了。
nuanyangyang机器人#5 · 2016/6/26
狗表示压力很大 【 在 aquamarine 的大作中提到: 】 : 用bitstruct解决了。。。 : 本来真的是想DRY的。。。结果发现处处日狗。。。疯了 :