在Python中转换结构体
我正在使用ctypes从一个外部数据库读取一些数据。
这些数据是以结构体的形式写的。问题是,接收到的数据可能会有不同的结果。为了更好地理解,我创建了两个结构体:
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: must be a ctypes type。
这是我的代码:
'''
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()
谢谢你的帮助。
解决方案:
通过阅读 这个帖子,我修改了@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 个回答
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)
(输出结果是一样的)