Re: [Numpy-discussion] Troubles with arrays, proposal for Solution
Vanroose Wim writes:
Dear Numerical Python Users,
It is now clear to me, after the comments of Travis Oliphant, Paul Dubois and Phil Austin, that in EVERY C-file that uses NumPy extensions, the "import_array" statement must be present.
Actually, what I was trying to say (in a message that didn't make it to the list) is the opposite -- import_array must be present in only one file. So below I would do something like: (my additions marked by PA>)
///////////////////////// //file: arraytest.h //////////////////////
#include "Python.h"
PA> #define PY_ARRAY_UNIQUE_SYMBOL paArray
#include "arrayobject.h"
double *myTest(void);
////////////////////// // file: arraytest.c ////////////////////
PA> #define NO_IMPORT_ARRAY
#include "arraytest.h"
double * myTest(void ){ double *result; ...
return result; }
//////////////////// //file: test.c //////////////// #include "arraytest.h"
static PyObject *function(PyObject *self, PyObject *args){
... int dimensions[2];
dimensions[0] = N; dimensions[1] = N;
PyArrayObject *result ; result = (PyArrayObject *)PyArray_FromDims(2,dimensions,PyArray_DOUBLE);
double *data; data = myTest(); memcpy(result->data,data,N*N*sizeof(double)); return PyArray_Return(result); }
static PyMethodDef testMethods[] = { {"test",function,1}, {NULL,NULL} };
extern "C" { void inittest(){ PyObject *m,*d; m = Py_InitModule("test", testMethods); import_array(); d = PyModule_GetDict(m); }
You should see the following when you run /lib/cpp -E on these files: in arraytest.c #define NO_IMPORT_ARRAY #include "arraytest.h" will produce a line like: extern void **paArray; but in test.c #include "arraytest.h" will produce: void **paArray; and import_array(); will expand to { PyObject *numpy = PyImport_ImportModule("_numpy"); if (numpy != 0) { PyObject *module_dict = PyModule_GetDict(numpy); PyObject *c_api_object = PyDict_GetItemString(module_dict, "_ARRAY_API"); if (((c_api_object)->ob_type == &PyCObject_Type)) { paArray = (void **)PyCObject_AsVoidPtr(c_api_object); } } }; The result is that there is a single global function pointer array called paArray that has its space reserved in test.c, and is referenced externally in arraytest.c. This allows you to use any numeric api call in either file. If you compile the module to, say, test.so on unix you should see something like this when you do a nm -D: ~phil% nm -D test.so | grep paArray 000a3d00 B paArray i.e. one instance of paArray in the data segment of the so file. Scanning the output of /lib/cpp -E output is a good way to get a feel for this (on unix anyway). Regards, Phil
participants (1)
-
Phil Austin