2016-06-25 4 views
0

VS私が「コンパクト化」のバイナリに、このような構造体をシリアル化する意図:のpythonのctype _pack_ G ++の#pragma pack

#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; 
}; 

それはここでうまく動作し、クラス「foo」というの大きさがある、9ですまさに私が欲しいものです。

しかし、これをPython ctypes libで再実装しようとすると、すべてが間違っています。

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) 

RawMessageの大きさは、私が「パック」プロパティがまったく動作しないと思います12です。メッセージmのバイナリ表現は "ff000000ffffffffffffffff"です。

これは混乱する問題です。それで私を助けてください。

ありがとうございました。

+0

私は問題を解決するために周りの作業として "bitstruct" を使用します。 "ctypes"は本当にそれを作ることができない、または少なくとも、この問題を完全に解決することはできません。 – Wizmann

答えて

0

あなたがRawMessageのはsizeofは9になりたい場合は、(あなたが唯一の4バイト/ 32ビットであるc_ulongを使用)、符号なし64ビットフィールドのビット・フィールドのc_uint8c_ulonglongを使用する必要があります。

のpython 3のコードに、しかし、アイデアは、2.7をPythonでは、転移する必要があります:

#!/usr/bin/python3 
import ctypes 
import io 
import binascii 

class RawMessage(ctypes.Structure): 
    _pack_ = 1 
    _fields_ = [ 
     ('a', ctypes.c_uint8 , 1), 
     ('b', ctypes.c_uint8 , 2), 
     ('c', ctypes.c_uint8 , 5), 
     ('d', ctypes.c_ulonglong), 
    ] 

def dump(o): 
    s = io.BytesIO() 
    s.write(o) 
    s.seek(0) 
    return binascii.hexlify(s.read()) 

def bin_dump(byte_buff): 
    s_buff = list() 
    for abyte in byte_buff: 
     s_buff.append("{:08b}".format(abyte)) 
    return "".join(s_buff) 

if __name__ == '__main__': 
    m = RawMessage() 
    m.a = 1 # 1 
    m.b = 1 # 01 
    m.c = int('11111', 2) # 11111 
    m.d = 0x7ffffffffffffffe # 1st and last bit set to 0 

    # note : m.a, m.b and m.c should read: 
    # 11111 01 1 -> 11111011 -> 0xfb 

    print("size of RawMessage: {}".format(ctypes.sizeof(m))) 
    buf = (ctypes.c_char * ctypes.sizeof(m)).from_buffer_copy(m) 
    bytes_buff = bytes(buf) 
    print("buffer: {}".format(bytes_buff)) 

    #print(bin_dump(bytes_buff)) 

    print(dump(m)) 

出力:

$> py -3 so_ctypes.py 
size of RawMessage: 9 
buffer: b'\xfb\xfe\xff\xff\xff\xff\xff\xff\x7f' 
b'fbfeffffffffffff7f'