
I did some experimenting with the NumPy C API. I wrote two functions. One for processing a NumPy array in C++ and the other one for generating a NumPy array in C++. The processing function work perfectly fine. But in the array-generating function I get a segmentation fault whenever I call PyArray_FromDims. I used swig for generating the wrapper functions. The two src-files (numPyExt.i and numPyExt.cc): --- begin numPyExt.i ------------------------------------------------- %module numPyExt %{ #include <iostream.h> #include <Python.h> #include <Numeric/arrayobject.h> %} %init %{ import_array(); %} %typemap(python,in) double * { PyArrayObject *py_arr; if(!PyArray_Check($source)) { PyErr_SetString(PyExc_TypeError, "Not a NumPy array"); return NULL; } if (PyArray_ObjectType($source,0) != PyArray_DOUBLE) { PyErr_SetString(PyExc_ValueError, "Array must be of type double"); return NULL; } py_arr = (PyArrayObject*) \ (PyArray_ContiguousFromObject($source, PyArray_DOUBLE, 1, 1)); if (py_arr->nd != 1) { PyErr_SetString(PyExc_TypeError, "Array must be 1D"); return NULL; } $target = (double*)(py_arr->data); } extern PyObject* createArray(); extern void processArray(double* pdInArray); --- end numPyExt.i --------------------------------------------------- --- begin numPyExt.cc ------------------------------------------------ #include <iostream.h> #include <Python.h> #include <Numeric/arrayobject.h> //------ PyObject* createArray() { PyArrayObject* retArray; int iDimensions[3] = {10, 10, 10}; cout << "before PyArray_FromDims" << endl << flush; retArray = (PyArrayObject*)PyArray_FromDims(3, iDimensions, PyArray_INT); cout << "after PyArray_FromDims" << endl << flush; return PyArray_Return(retArray); } //------ void processArray(double* pdInArray) { cout << *pdInArray << " " << *(pdInArray+1) << " " << *(pdInArray+2) << endl; } --- end numPyExt.cc -------------------------------------------------- Compiled with: g++ -c -I/usr/local/include/python2.0 -I/usr/local/lib/python2.0/site-packages -O2 numPyExt.cc swig -python -c++ numPyExt.i g++ -c -O2 numPyExt_wrap.c -DOS_LINUX -DHAVE_CONFIG_H -I. -I/usr/local/include/python2.0 -I/usr/local/lib/python2.0/site-packages -I/usr/local/lib/python2.0/config g++ -W1,--heap,50000,--stack,100000 -O2 -shared numPyExt.o numPyExt_wrap.o -lstdc++ -o numPyExt.so The Python test code I am using: import Numeric, numPyExt vec = Numeric.array((1.23, 4.56, 7.89)) numPyExt.processArray(vec) # works fine a = numPyExt.createArray() # seg fault here print a I am using NumPy v20.0.0, Python 2.1, and gcc 2.95.2 on a Linux 2.2.16 sytem. Does anybody have an idea what's causing this problem? Juerg

At some point, Juerg Tschirren <juerg-tschirren@uiowa.edu> wrote:
I did some experimenting with the NumPy C API. I wrote two functions. One for processing a NumPy array in C++ and the other one for generating a NumPy array in C++. The processing function work perfectly fine. But in the array-generating function I get a segmentation fault whenever I call PyArray_FromDims. I used swig for generating the wrapper functions.
The two src-files (numPyExt.i and numPyExt.cc):
[code snipped]
Compiled with: g++ -c -I/usr/local/include/python2.0 -I/usr/local/lib/python2.0/site-packages -O2 numPyExt.cc swig -python -c++ numPyExt.i g++ -c -O2 numPyExt_wrap.c -DOS_LINUX -DHAVE_CONFIG_H -I. -I/usr/local/include/python2.0 -I/usr/local/lib/python2.0/site-packages -I/usr/local/lib/python2.0/config g++ -W1,--heap,50000,--stack,100000 -O2 -shared numPyExt.o numPyExt_wrap.o -lstdc++ -o numPyExt.so
This problem was discussed in April on this list, see http://www.geocrawler.com/mail/thread.php3?subject=%5BNumpy-discussion%5D+Numeric+on+OS+X+-+Anyone+get+it+to+work+%3F&list=1329 I banged my head against this for hours a few weeks ago until I found the above. The problem is that PyArray_FromDims (and all other PyArray_*) are not functions -- they're macros, defined like this: #define PyArray_FromDims \ (*(PyArray_FromDims_RET (*)PyArray_FromDims_PROTO) \ PyArray_API[PyArray_FromDims_NUM]) This means that all the PyArray_* functions are done through a lookup table PyArray_API, which is initialized by import_array(). By default, PyArray_API is defined in arrayobject.h as 'static void **PyArray_API', meaning that it is not accessible outside of the translation unit (i.e. file) that includes it. The relevant part of Numeric/arrayobject.h is this: #if defined(PY_ARRAY_UNIQUE_SYMBOL) #define PyArray_API PY_ARRAY_UNIQUE_SYMBOL #endif /* C API address pointer */ #if defined(NO_IMPORT) || defined(NO_IMPORT_ARRAY) extern void **PyArray_API; #else #if defined(PY_ARRAY_UNIQUE_SYMBOL) void **PyArray_API; #else static void **PyArray_API; #endif #endif So, one way to get the behaviour you want is 1) in the file where import_array is called, #define PY_ARRAY_UNIQUE_SYMBOL to be something like Py_Array_API_myext. (Make it unique because it will be exported as part of the .so file.) before including Numeric/arrayobject.h 2) in the other files, #define NO_IMPORT_ARRAY before including Numeric/arrayobject.h Another way is to have your main file (say, main.c) call functions in the other files, passing the value of PyArray_API defined there, so that the other files can set theirs to that value. Hope this helps. -- |>|\/|< /--------------------------------------------------------------------------\ |David M. Cooke |cookedm@physics.mcmaster.ca
participants (2)
-
cookedm@physics.mcmaster.ca
-
Juerg Tschirren