'How to assign value to zero-length array defined by ctypes in Python3
Here I have a class defined like below, whose attribute data
is a zero-length array. How to instantiate this class?
class Frame(ctypes.Structure):
_fields_ = [
("id", ctypes.c_uint64),
("size", ctypes.c_uint32),
("data", ctypes.c_byte*0) # zero-length array
]
I tried this
frame = Frame()
frame.id = 0
frame.size = 2
frame.data = ctypes.cast(b'12', ctypes.POINTER(ctypes.c_type * 0))
but an exception was raised at line 4
TypeError: incompatible types, LP_c_byte_Array_0 instance instead of c_byte_Array_0 instance
so, how should I do to instantiate this class correctly?
Solution 1:[1]
Listing [Python.Docs]: ctypes - A foreign function library for Python.
This technique (having a struct with a 0 lengthed array as last member) is commonly used in C in order to have variable data right after the struct.
Unfortunately, the Python layer doesn't allow that (assigning to an array a value larger than its length). The closest thing to your goal would be to declare the data member as a pointer. Going further, create a setter method that does all conversions:
code00.py:
#!/usr/bin/env python3
import ctypes as ct
import sys
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(*argv):
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 {:s} {:03d}bit on {:s}\n".format(" ".join(elem.strip() for elem in sys.version.split("\n")),
64 if sys.maxsize > 0x100000000 else 32, sys.platform))
rc = main(*sys.argv[1:])
print("\nDone.")
sys.exit(rc)
Output:
[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)] 064bit on win32 0 - 49 1 - 50 2 - 51 3 - 97 4 - 98 5 - 67 6 - 68 Done.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |