BYTE到python C-Type结构转换问题

时间:2012-12-24 16:19:14

标签: python python-2.7 structure ctypes

我在对从POSIX队列接收的一些字节进行反序列化方面遇到了一些问题。

我们正在尝试开发一个模块,其中Python应用程序将POSIX队列数据发布到C应用程序,C将重新发布数据到Python Queue ..

所有数据均基于Ctype结构。

结构定义:

msgStruct.py

MAX_MSG_SIZE = 5120
class MsgStruct(ctypes.Structure):
    _fields_ = [
                ("msgType", ctypes.c_int),
                ("msgSize",ctypes.c_int),
                ("setState",ctypes.c_int),
                ("msgBuf",ctypes.c_char * MAX_MSG_SIZE)
            ]

conversions.py

class conversions():
    def serialize(ctypesObj):
        """
        FAQ: How do I copy bytes to Python from a ctypes.Structure?
        """
        return buffer(ctypesObj)[:]

    def deserialize(ctypesObj, inputBytes):
        """
        FAQ: How do I copy bytes to a ctypes.Structure from Python?
        """
        fit = min(len(inputBytes), ctypes.sizeof(ctypesObj))
        ctypes.memmove(ctypes.addressof(ctypesObj), inputBytes, fit)
        return ctypesObj    

test.py

from mapStruct import *
from conversions import conversions
wrapper=conversions()
data="\x01\x00\x00\x00\x70\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x1e\x00\x00\x00\x25\x42\x35\x32\x33\x39\x35\x31\x32\x35\x32\x34\x38\x39\x35\x30\x30\x36\x5e\x56\x45\x4e\x4b\x41\x54\x20\x52\x41\x47\x41\x56\x41\x4e\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x5e\x31\x36\x30\x34\x31\x30\x31\x31\x36\x35\x35\x36\x30\x30\x31\x34\x31\x30\x30\x30\x30\x30\x30\x3f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x3b\x35\x32\x33\x39\x35\x31\x32\x35\x32\x34\x38\x39\x35\x30\x30\x36\x3d\x31\x36\x30\x34\x31\x30\x31\x31\x34\x31\x30\x3f\x00\x00...\x00"
"""
Data is the Queue data that is recieved by python
"""
baseStruct=MsgStruct()
rxData=wrapper.deserialize(baseStruct,data)
print rxData.setState # Prints as expected
print rxData.msgType # Prints as expected
print rxData.msgSize
print rxData.msgBuf.encode('hex') # here is probles i dont C any data in this buffer

请指导我解决这个问题。我非常惊讶缓冲区(rxData.msgSize)总是空的,想知道原因。

2 个答案:

答案 0 :(得分:2)

ctypes试图通过将c_char缓冲区转换为Python字符串来提供帮助。转换在第一个空字节处停止。观察当我更改数据缓冲区中数据的前几个字节时会发生什么:

0
1
368
b'\x01\x02'

msgBuf的类型更改为c_ubyte,以便ctypes不会尝试“有用”,然后逐个字符地查看数据:

>>> print repr(''.join(chr(x) for x in rxData.msgBuf))
'\x00\x00\x00\x00\x02\x00\x00\x00\x1e\x00\x00\x00%B5239512524 ...

但根本没有理由使用ctypes

import struct

data=b"\x01\x00\x00\x00\x70\x01\x00\x00\x00\x00\x00\x00\x01\x02\x00\x00\x02\x00\x00\x00\x1e\x00\x00\x00\x25\x42\x35\x32\x33\x39\x35\x31\x32\x35\x32\x34\x38\x39\x35\x30\x30\x36\x5e\x56\x45\x4e\x4b\x41\x54\x20\x52\x41\x47\x41\x56\x41\x4e\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x5e\x31\x36\x30\x34\x31\x30\x31\x31\x36\x35\x35\x36\x30\x30\x31\x34\x31\x30\x30\x30\x30\x30\x30\x3f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x3b\x35\x32\x33\x39\x35\x31\x32\x35\x32\x34\x38\x39\x35\x30\x30\x36\x3d\x31\x36\x30\x34\x31\x30\x31\x31\x34\x31\x30\x3f\x00\x00...\x00"

msg_offset = struct.calcsize('iii')
print struct.unpack_from('iii',data)
print repr(data[msg_offset:])

输出:

(1, 368, 0)
'\x01\x02\x00\x00\x02\x00\x00\x00\x1e\x00\x00\x00%B5239512524895006^VENKAT RAGAVAN            ^16041011655600141000000?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00;5239512524895006=16041011410?\x00\x00...\x00'

答案 1 :(得分:0)

您可以使用struct为您解压缩数据:

import struct
import ctypes

class MsgStruct(ctypes.Structure):
    _fields_ = [
                ("msgType", ctypes.c_int),
                ("msgSize",ctypes.c_int),
                ("setState",ctypes.c_int),
                ("msgBuf",ctypes.c_char * 5120)
            ]

def deserialize(data):
    sz = len(data)-struct.calcsize('iii')
    return MsgStruct(*struct.unpack('iii{}s'.format(sz), data))

使用您的数据进行测试:

In [18]: data
Out[18]: '\x01\x00\x00\x00p\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x1e\x00\x00\x00%B5239512524895006^VENKAT RAGAVAN            ^16041011655600141000000?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00;5239512524895006=16041011410?\x00\x00...\x00'

In [19]: s = deserialize(data)

In [20]: s.
s.msgBuf    s.msgSize   s.msgType   s.setState  

In [20]: s.msgType
Out[20]: 1

In [21]: s.msgSize
Out[21]: 368

In [22]: s.setState
Out[22]: 0

修改: MsgStruct作业不适用于msgBuf字段。请查看this question的答案。解压缩结构可以正常工作:

In [13]: sz=12

In [14]: struct.unpack('iii{}s'.format(len(data)-sz), data)
Out[14]: (1, 368, 0, '\x00\x00\x00\x00\x02\x00\x00\x00\x1e\x00\x00\x00%B5239512524895006^VENKAT RAGAVAN            ^16041011655600141000000?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00;5239512524895006=16041011410?\x00\x00...\x00')