[Pyrex] Access to nested structures and arrays
Pierre GM
pgmdevlist at gmail.com
Fri Mar 16 17:29:07 UTC 2007
All,
I'm using Pyrex to write an interface between Python and an external C/fortran
code. This code involves some nested structures whose individual elements I
need to access from python.
I started to unwrap the nested structure, creating one extension type for each
substructure. For example, I have this kind of definition in the ".pxd" part:
#............................
ctypedef struct c_model "model":
double span
int parametric[8]
ctypedef struct c_nested "base":
c_inputs inputs
c_model model
#............................
Which becomes that in the ".pyx" part:
cdef class l_model:
cdef c_loess.c_model *_base
cdef long npar
#.........
property span:
def __get__(self):
return self._base.span
def __set__(self, span):
if span <= 0 or span >= 1:
raise ValueError("Span should be comprised between 0 and 1!")
self._base.span = span
#.........
property parametric_flags:
def __get__(self):
return boolarray_from_data(self.npar, 1, self._base.parametric)
def __set__(self, paramf):
cdef ndarray p_ndr
cdef long *p_dat
cdef int i
p_ndr = numpy.array(paramf, copy=False, subok=True,
dtype=numpy.int)
p_dat = <long *>p_ndr.data
for i from 0 <= i < min(self.npar, p_ndr.size - 1):
self._base.parametric[i] = p_dat[i]
#............................
(where boolarray is a function that takes a C pointer and returns a numpy
ndarray).
To initialize this extension type, I use this:
locmodel = l_model()
locmodel._base = &nested_structure._model
locmodel.npar = npar
where nested_structure is the underlying C base structure.
I tried to define a special __init__ method for l_model, that would take a
pointer to the _model substructure and npar as arguments. That doesn't work,
because _model cannot be transformed to a Python object.
First question:
When writing extension types, am I limited to use only Python objects as
arguments of __init__ ?
Using properties was the quickest way I found to access the elements of the
underlying C substructure, but that looks a bit bloated: I'm putting layers
over layers.
Second question:
isn't there a better way than that ?
Finally, using properties is fine up to a point. Some elements of the
substructures are pointers to C arrays (for example, parametric in c_model).
I need to read and write to these arrays. Reading is fine, but I have a
problem with writing: the __set__ method I use lets me write the whole array
at once, but I'd like to modify some individual elements.
For example:
>>>X = l_model.parametric_flags
X is a ndarray, everything's fine
>>>l_model.parametric_flags = X[::-1]
I'm setting the whole array at once, so that's fine as well. But now,
>>>l_model.parametric_flags[0] = True
will NOT update the first element of the underlying C substructure,
c_model.parametric, as I'd like it to.
Third question:
how can I modify the underlying C array from Python ?
I hope it doesn't sound too confusing. I'm still very new to C and Pyrex, I'm
sure you'll be lenient.
Thanks a lot in advance for any idea/comments.
More information about the Pyrex
mailing list