On Wed, Jun 15, 2011 at 5:36 AM, Robert Cimrman cimr...@ntc.zcu.cz wrote:
Hi
any Cython expert around (Ondrej?).
Our build system already supports cython extension modules and I succeeded in using it for simple stuff, like the sfepy/fem/physics/extmods/cdft.pyx, see [1].
Now I would like to proceed further, but am only a beginner, so an advice would come handy:
I need to map somehow numpy arrays to the FMField struct defined in sfepy/fem/extmods/fmfield.h to be able to export C functions (e.g. term evaluation functions) to Python and pass numpy arrays in. What is the best way to do this? Also being able to call Python from C would be nice (e.g. some numpy array functions).
Here is an example how to get to the pointer of the C array in numpy:
def atom_lda2(int Z, ndarray[double, mode="c"] R not None, ndarray[double, mode="c"] Rp not None, ndarray[int, mode="c"] no not None, ndarray[int, mode="c"] lo not None, ndarray[double, mode="c"] fo not None, ndarray[double, mode="c"] V_tot not None, ndarray[double, mode="c"] ks_energies not None, double reigen_eps, int reigen_max_iter, double mixing_eps, double mixing_alpha, int mixing_max_iter): cdef int n = len(R) cdef int n_orb = len(no) assert len(Rp) == n assert len(V_tot) == n assert len(lo) == n_orb assert len(fo) == n_orb assert len(ks_energies) == n_orb cdef double E_tot cdef ndarray[double, mode="c"] density = empty(n) cdef ndarray[double, ndim=2, mode="fortran"] orbitals = empty((n, n_orb), order="F")
rdirac.c_atom_lda2(&n, &n_orb, &Z, &R[0], &Rp[0],
&no[0], &lo[0], &fo[0], &V_tot[0], &ks_energies[0], &E_tot,
&density[0], &orbitals[0, 0],
&reigen_eps, &reigen_max_iter, &mixing_eps, &mixing_alpha,
&mixing_max_iter)
return E_tot, density, orbitals
And C the signature of the rdirac.c_atom_lda2 function is:
cdef extern void c_atom_lda2(int *n, int *n_orb, int *Z, double *R, double *Rp, int *no, int *lo, double *fo, double *V_tot, double *ks_energies, double *E_tot, double *density, double *orbitals, double *reigen_eps, int *reigen_max_iter, double *mixing_eps, double *mixing_alpha, int *mixing_max_iter)
This function is implemented directly in Fortran, but in your case, you can implement it in C. In C, you might want to pass some variables directly (not by reference), so instead of doing "&n" above, you would just do "n". Makes sense?
So here is the field:
typedef struct FMField { int32 nCell; int32 nLev; int32 nRow; int32 nCol; float64 *val0; float64 *val; int32 nAlloc; int32 cellSize;
int32 offset; int32 nColFull;
int32 stride; } FMField;
So tell me more how you want to use it. Who owns the memory? The easiest (see above) is when Python allocates all the memory, and then you just pass a reference to it to C/Fortran, and it fills it in.
(Why all this?
- Cython wrappers are much lighter compared to swig ones -> less call overhead.
- Cython code looks like Python, so it's easier to write fast code.
- it's cool :))
+1
Ondrej