Ever since I read Dave Beazley's post on binary I/O handling (http://dabeaz.blogspot.com/2009/08/python-binary-io-handling.html) I've wanted to create a Python library for a certain wire protocol. However, I can't find the best solution for variable length structures. Here's what I want to do:
import ctypes as c
class Point(c.Structure):
_fields_ = [
('x',c.c_double),
('y',c.c_double),
('z',c.c_double)
]
class Points(c.Structure):
_fields_ = [
('num_points', c.c_uint32),
('points', Point*num_points) # num_points not yet defined!
]
The class Points
won't work since num_points
isn't defined yet. I could redefine the _fields_
variable later once num_points
is known, but since it's a class variable it would effect all of the other Points
instances.
What is a pythonic solution to this problem?
ctypes is a foreign function library for Python. It provides C compatible data types, and allows calling functions in DLLs or shared libraries. It can be used to wrap these libraries in pure Python.
c_char_p is a subclass of _SimpleCData , with _type_ == 'z' . The __init__ method calls the type's setfunc , which for simple type 'z' is z_set . In Python 2, the z_set function (2.7. 7) is written to handle both str and unicode strings.
The most straightforward way, with the example you gave is to define the structure just when you have the information you need.
A simple way of doing that is creating the class at the point you will use it, not at module root - you can, for example, just put the class
body inside a function, that will act as a factory - I think that is the most readable way.
import ctypes as c
class Point(c.Structure):
_fields_ = [
('x',c.c_double),
('y',c.c_double),
('z',c.c_double)
]
def points_factory(num_points):
class Points(c.Structure):
_fields_ = [
('num_points', c.c_uint32),
('points', Point*num_points)
]
return Points
#and when you need it in the code:
Points = points_factory(5)
Sorry - It is the C code that will "fill in" the values for you - that is not the answer them. WIll post another way.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With