【问题标题】:Convert byte array to Ctype struct values将字节数组转换为 Ctype 结构值
【发布时间】:2020-08-10 18:03:24
【问题描述】:

我只想使用具有 C# 文档中指定的以下结构的 python 将原始字节数组(未知编码)转换为 Ctype 值。但是输出不正确。我的意思是,LTP 显示为负数,但事实并非如此。如果我缺少某些编码,请指导。

我只想要 LTP 字段,我尝试使用偏移量仍然值不正确。我可以将字节位置直接转换为Ctype值还是有其他方法?

结构

字节位置:1-2 类型:int8 字段:交换

字节位置:2-6 类型:int32 字段:仪器令牌

字节位置:6-10 类型:int32 字段:Ltp

字节位置:10-14 类型:int32 字段:更改

字节位置:14-18 类型:int32 字段:交换时间戳

字节位置:18-22 类型:int32 字段:卷

from ctypes import Structure,c_int32, c_byte

class CompactMarketData(Structure):
    _fields_ = [("Mode", c_byte),("Exchange", c_byte),("InstrumentToken", c_int32), ("LastTradedPrice", c_int32), ("Change", c_int32), ("ExchangeTimeStamp", c_int32), ("Volume", c_int32)]

def main():
    raw=b'\x02\x06\x00\x08;8\x00\x01n\x04\xff\xff\xff\x06_0\xc5\xea\x00\x00",_0\xc5\xea'
    b = bytearray(raw)
    s = CompactMarketData.from_buffer(b)

    print("Mode: "+format(s.Mode))
    print("Exchange: "+format(s.Exchange))
    print("InstrumentToken: "+format(s.InstrumentToken))
    print("LastTradedPrice: ",str(s.LastTradedPrice))
    print("Change: "+format(s.Change))
    print("ExchangeTimeStamp: "+format(s.ExchangeTimeStamp))
    print("Volume: "+format(s.Volume))

if __name__ == '__main__':
    main()

输出:

交换:2

仪器令牌:16791611

最后交易价格:-64402

更改:811534079

交换时间戳:60101

数量:811543586

【问题讨论】:

  • 缓冲区和结构大小不一致(26 与 22)。你知道原始数据字节应该翻译成什么吗?拥有示例输入和正确的所需输出将有助于解决您的问题。

标签: python arrays python-3.7 ctypes


【解决方案1】:

使用_pack_ = 1documentation)结构属性满足条件:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from ctypes import Structure, c_int32, c_byte


class CompactMarketData(Structure):
    _pack_ = 1
    _fields_ = [
        ("Mode", c_byte),
        ("Exchange", c_byte),
        ("InstrumentToken", c_int32),
        ("LastTradedPrice", c_int32),
        ("Change", c_int32),
        ("ExchangeTimeStamp", c_int32),
        ("Volume", c_int32)
    ]

    def view_offsets(self):
        for field in self._fields_:
            name, field_type = field
            field_start = getattr(self.__class__, name).offset
            field_end = field_start + ctypes.sizeof(field_type)
            print(f"{name} - {field_start}:{field_end}")



def main():
    raw=b'\x02\x06\x00\x08;8\x00\x01n\x04\xff\xff\xff\x06_0\xc5\xea\x00\x00",_0\xc5\xea'
    b = bytearray(raw)
    s = CompactMarketData.from_buffer(b)

    s.view_offsets()

    print(f"\n{'-' * 79}")

    print(f"Struct Size: {ctypes.sizeof(CompactMarketData)}")
    print(f"buffer len: {len(raw)}")

    print(f"Mode: {s.Mode:#x}")
    print(f"Exchange: {s.Exchange:#x}")
    print(f"InstrumentToken: {s.InstrumentToken:#x}")
    print(f"LastTradedPrice: {s.LastTradedPrice:#x}")
    print(f"Change: {s.Change:#x}")
    print(f"ExchangeTimeStamp: {s.ExchangeTimeStamp:#x}")
    print(f"Volume: {s.Volume:#x}")


if __name__ == "__main__":
    main()

输出:

Mode - 0:1
Exchange - 1:2
InstrumentToken - 2:6
LastTradedPrice - 6:10
Change - 10:14
ExchangeTimeStamp - 14:18
Volume - 18:22

-------------------------------------------------------------------------------
Struct Size: 22
buffer len: 26
Mode: 0x2
Exchange: 0x6
InstrumentToken: 0x383b0800
LastTradedPrice: 0x46e0100
Change: 0x6ffffff
ExchangeTimeStamp: -0x153acfa1
Volume: 0x2c220000

注意:请注意您的字节缓冲区长于结构的大小。

【讨论】:

  • 非常感谢 Neitsa。我知道我错过了什么。我必须处理缓冲区长度和结构大小。输出是十六进制格式,所以我需要转换它。正确的?请告诉我将其转换为十进制的正确方法。再次感谢您。
  • @Rajnikant 输出是十六进制的,因为从我的角度来看,更容易看出缓冲区的哪一部分最终出现在哪个字段中(例如,InstrumentToken 来自\x00\x08;8)。除此之外,十六进制或十进制是相同值的不同表示,但最终的值仍然相同。如果要打印十进制而不是十六进制,只需删除 f 字符串中的格式,即:#x
  • 好的,Neitsa。非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-09-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-11
  • 2015-11-18
  • 1970-01-01
相关资源
最近更新 更多