From: Sebastian H. <ha...@ms...> - 2003-03-10 20:32:45
|
<snip> > Well, in case you (or others) find it useful, I'm including here a little > library I wrote for accessing general Numeric 2-d arrays (contiguous or not) > in an easy manner. > > Here's a snippet of a simple (included) example of a function to print an > integer array: > > static PyObject *idisp(PyObject *self, PyObject *args) > { > PyArrayObject *array; > int **arr; // for the data area > int i,j,cs; > > if (!PyArg_ParseTuple(args, "O!",&PyArray_Type,&array ) ) > return NULL; > > arr = imatrix_data(array,&cs); > for (i=0;i<array->dimensions[0];++i) { > for (j=0;j<cs*array->dimensions[1];j+=cs) > printf("%5d ",arr[i][j]); > printf("\n"); > } > free(arr); > > Py_INCREF(Py_None); > return Py_None; > } > > You get the **arr pointer and you can then manipulate it as a[i][j] > conveniently. The supplied example file may be enough for many to write their > Numpy C extensions without much trouble. > > > Again: thanks so much. > > BTW: Is there general interest in my SWIG typemaps. (SWIG is maybe the > > easiest way to wrap C/C++ functions (and classes) > > into Python (and/or Perl, Java, Ruby,...) ? I think especially for > > numerical stuff, that "link" in of interest. > > I'd love to see them. So far I've either used high-level stuff like > weave.inline() or just written the extensions by hand (as in the code I'm > supplying here). I'd like to see this, especially if there is an easy way to > handle contiguity issues with it. You are using Numeric not numarray , right? In any case : My thinking goes as follows: I was looking for a wrapping-solution that would be most transparent to the people that would write the C/C++ code (or even Fortran, BTW) Since I already had some experience using SWIG, that's what I wanted to use to handle the "numarray binding". SWIG has a quite strong (meaning: flexible, general) way of handling data types. They call it "type maps": Once you have that in place (later more) the whole "binding" looks like this: (an example) C side: double sebFunc(float *arr, int nx, int ny, int nz) { double a =0; for(int i=0;i<nx*ny*nz;i++) a+= arr[i]; return a; } Then there is the SWIG interface file (suggested file extension ".i"): double sebFunc(float *array3d, int nx, int ny, int nz); ((This has (in firts approx.) the same syntax as a normal C-header file - just that SWIG "bites" on the argument-variable names, in this case (float *array3d, int nx, int ny, int nz) and realizes (because of my "type map") that this should be a python-(numeric) array Then you call it from python just like that... import myModule print myModule.sebFunc(array) So the magic is all hidden in the the typemap: For that I have a separate SWIG-interface that gets #included into the above mentioned one. Here is that interface file ( just the part for 3d float arrays) %typecheck(SWIG_TYPECHECK_FLOAT) (float *array2d, int nx, int ny) { if(!PyArray_Check($input)) $1=0; else if(((PyArrayObject*)$input)->descr->type_num != tFloat32) $1=0; else if(((PyArrayObject*)$input)->nd != 2) $1=0; else $1=1; } %typemap(python,in) (float *array3d, int nx, int ny, int nz) (PyArrayObject *temp=NULL) { debugPrintf("debug: float *array3d -> NA_InputArray\n"); PyArrayObject *NAimg = NA_InputArray($input, tFloat32, NUM_C_ARRAY); if (!NAimg) { printf("**** no (float) numarray *****\n"); return 0; } temp = NAimg; $1 = (float *) (NAimg->data + NAimg->byteoffset); switch(NAimg->nd) { case 1: $2 = NAimg->dimensions[0]; $3=1; break; case 2: $2 = NAimg->dimensions[1]; $3=NAimg->dimensions[0]; break; default: debugPrintf(" **** numarray dim >2 (ns=%d)\n", NAimg->nd); _SWIG_exception(SWIG_RuntimeError, "numarray dim > 2"); return 0; } %typemap(python,freearg) (float *array3d, int nx, int ny, int nz) { Py_XDECREF(temp$argnum); } The first part (%typecheck) is needed so that SWIG call even handle overloaded functioned correctly. (BTW, SWIG happily wraps my template functions to; just with classes (that keep a reference to an array) I not that sure yet [reference counting]) I think I don't have all necessary error handling parts implemented yet. But this is already a VERY useful tool for me - and I am in fact working right now on convincing some ( C and Fortran only) people to try this ;-) [ once they see how cool it is to call their (Fortran or C) directly from Python, maybe they start to realize that there is "something new out there" (emm, I meant Python ] So what is the status on this list: Are people familiar with (know and/or using) SWIG ? Cheers, Sebastian |