在这里,我有一个如下所示的类,其属性data
是一个零长度数组。如何实例化此类?
class Frame(ctypes.Structure):
_fields_ = [
("id", ctypes.c_uint64),
("size", ctypes.c_uint32),
("data", ctypes.c_byte*0) # zero-length array
]
我尝试过
frame = Frame()
frame.id = 0
frame.size = 2
frame.data = ctypes.cast(b'12', ctypes.POINTER(ctypes.c_type * 0))
但第4行出现了异常
TypeError: incompatible types, LP_c_byte_Array_0 instance instead of c_byte_Array_0 instance
那么,如何正确实例化此类?
答案 0 :(得分:1)
列出[Python 3.Docs]: ctypes - A foreign function library for Python。
此技术(具有 0 长数组作为最后一个成员的 struct )通常用于 C 中,以获取可变数据在 struct 之后。
不幸的是, Python 层不允许这样做(将大于其长度的值分配给数组)。与您的目标最接近的事情是将 data 成员声明为指针。更进一步,创建一个执行所有转换的setter方法:
code00.py :
#!/usr/bin/env python3
import sys
import ctypes as ct
class Frame(ct.Structure):
_fields_ = [
("id", ct.c_uint64),
("size", ct.c_uint32),
("data", ct.POINTER(ct.c_ubyte)), # Make it a pointer
]
def set_data(self, value):
if not isinstance(value, (bytes,)):
raise ValueError("Bytes expected.")
self.data = ct.cast(value, ct.POINTER(ct.c_ubyte))
self.size = len(value)
def main():
frame = Frame()
frame.set_data(b"123abCD")
for i in range(frame.size):
print("{0:d} - {1:d}".format(i, frame.data[i]))
if __name__ == "__main__":
print("Python {0:s} {1:d}bit on {2:s}\n".format(" ".join(item.strip() for item in sys.version.split("\n")), 64 if sys.maxsize > 0x100000000 else 32, sys.platform))
main()
print("\nDone.")
输出:
[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q059172596]> "e:\Work\Dev\VEnvs\py_064_03.07.03_test0\Scripts\python.exe" code00.py Python 3.7.3 (v3.7.3:ef4ec6ed12, Mar 25 2019, 22:22:05) [MSC v.1916 64 bit (AMD64)] 64bit on win32 0 - 49 1 - 50 2 - 51 3 - 97 4 - 98 5 - 67 6 - 68 Done.