【问题标题】:BYTE to python C-Type structure Conversion IssueBYTE 到 python C-Type 结构的转换问题
【发布时间】:2012-12-24 16:19:14
【问题描述】:

我在反序列化从 POSIX 队列接收到的一些字节时遇到了一个小问题。

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

所有数据都是基于 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)总是空的,想知道为什么。

【问题讨论】:

  • deserialize() 返回 None 因为你没有明确地 return 其他东西。
  • @martineau:哎呀,在这里复制代码时我错过了..抱歉。它实际上返回 ctypesObj。
  • msgSize 字段是一个ctypes.c_int,那么您究竟希望msgSize.encode('hex') 做什么?
  • @martineau : 再次抱歉一个错字...更正它..而不是 msgBuf.encode('hex') 替换 msgSize.encode('hex')..my msgBUf 实际上包含另一个结构数据
  • wrapper.deserialize(data,baseStruct) 调用中的参数颠倒了。

标签: python python-2.7 structure ctypes


【解决方案1】:

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'

【讨论】:

    【解决方案2】:

    您可以使用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')
    

    【讨论】:

    • 仍然很困惑为什么 memove 没有做必要的事情。
    • 恐怕你必须研究 ctypes 的实现才能回答这个问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-18
    • 1970-01-01
    • 2022-01-05
    相关资源
    最近更新 更多