在python中强制转换结构

时间:2014-10-21 09:06:18

标签: python ctypes

我正在使用ctypes从外部数据库中读取一些数据。

这个数据是用struct编写的。问题是,收到的数据可能会有不同的结果。 对于更好的理解: 我创建了两个结构:

class BEAM(Structure):
    _fields_ = [
        ('NR', c_ulong),
        ("NODE1", c_ulong),
        ("NODE2", c_ulong),
        ("NP", c_ulong),
        ("DL", c_float),
        ("foo", c_ulong),
        ("foobar", c_ulong),
        ("bar", c_ulong),
        ("barfoo", c_ulong)
    ]

class DUMMY(Structure):
    _fields_ = [
        ('ID', c_ulong),
        ("NODE1", c_ulong),
        ("NODE2", c_ulong),
        ("NP", c_ulong),
        ("DL", c_ulong),
        ("foo", c_ulong),
        ("foobar", c_ulong),
        ("bar", c_ulong),
        ("barfoo", c_ulong)
    ]

这个结构之间的差异是“DL”中的u_long类型...在DUMMY中它是u_long,在BEAM中它是u_float。

读完数据库后我进入DL = 1056964624,但在浮点数应为0.5

我的问题是如何将DUMMY投射到BEAM中。

我试过了 BEAMRecord = cast(Record, POINTER(BEAMRecord))但是有一个错误叫做 TypeError:必须是ctypes类型

这是我的代码:

'''
Structure for DataLength
'''
class Len(Structure):
    _fields_ = [
        ('buffer', c_int)
    ]


SLNRecord = element.SLN()
BEAMRecord = element.BEAM()

Record = element.DUMMY()
RecLen = Len()

sofistik = cdll.LoadLibrary("cdb_w30_x64.dll")

py_sof_cdb_init = sofistik.sof_cdb_init
py_sof_cdb_close = sofistik.sof_cdb_close
py_sof_cdb_get = sofistik.sof_cdb_get

py_sof_cdb_get.restype = c_int

Index = py_sof_cdb_init("system.cdb", 99)

pos = c_int(0)

while True:
    RecLen.buffer = sizeof(Record)

    ie = py_sof_cdb_get(Index, 100, 0, byref(Record), byref(RecLen), pos)

    pos.value += 1

    if ie > 1:
        break

    if Record.ID > 0:
        BEAMRecord = cast(Record, POINTER(BEAMRecord))
        print BEAMRecord

py_sof_cdb_close(0)

exit()

感谢您的帮助


解决方案:

阅读this thread我修改了@Mr Temp问题

我创建了BEAMRecordPointer = POINTER(element.BEAM)BEAMRecord = cast(Record, POINTER(BEAMRecord))我重写为BAR = cast(byref(Record), BEAMRecordPointer).contents 所以解决方案看起来像这样

if Record.ID > 0:
        BAR = cast(byref(Record), BEAMRecordPointer).contents
        print BAR

我做错了?


更新1

@eryksun对于cast()函数有一个非常好的射击。谢谢。

1 个答案:

答案 0 :(得分:3)

您可以将结构加载到Union,然后根据需要访问它:

from ctypes import *

class BEAM(Structure):
    _fields_ = [('NR', c_ulong),
                ("NODE1", c_ulong),
                ("NODE2", c_ulong),
                ("NP", c_ulong),
                ("DL", c_float),
                ("foo", c_ulong),
                ("foobar", c_ulong),
                ("bar", c_ulong),
                ("barfoo", c_ulong)]

class DUMMY(Structure):
    _fields_ = [('ID', c_ulong),
                ("NODE1", c_ulong),
                ("NODE2", c_ulong),
                ("NP", c_ulong),
                ("DL", c_ulong),
                ("foo", c_ulong),
                ("foobar", c_ulong),
                ("bar", c_ulong),
                ("barfoo", c_ulong)]

class Both(Union):
    _fields_ = [('Beam',BEAM),('Dummy',DUMMY)]

x = Both()
x.Dummy.DL = 1056964624
print(x.Beam.DL)

输出:

0.5000009536743164

或更简单:

from ctypes import *

class DL(Union):
    _fields_ = [('DUMMY',c_ulong),('BEAM',c_float)]

class Hybrid(Structure):
    _fields_ = [('NR', c_ulong),
                ("NODE1", c_ulong),
                ("NODE2", c_ulong),
                ("NP", c_ulong),
                ("DL", DL),
                ("foo", c_ulong),
                ("foobar", c_ulong),
                ("bar", c_ulong),
                ("barfoo", c_ulong)]

x = Hybrid()
x.DL.DUMMY = 1056964624
print(x.DL.BEAM)

(相同的输出)