7

I wrote a simple Python extension function in C that just reads a Numpy array and it crashes.

static PyObject *test(PyObject *self, PyObject *args)
{
    PyArrayObject *array = NULL;

    if (!PyArg_ParseTuple(args, "O!", &PyArray_Type, &array)) // Crash
        return NULL;

    return Py_BuildValue("d", 0);
}

Here is how it is called:

l = np.array([1,2,3,1,2,2,1,3])

print("%d" % extension.test(l))

What's wrong with my code?

Rory Daulton
  • 21,934
  • 6
  • 42
  • 50
Mark Morrisson
  • 2,543
  • 4
  • 19
  • 25

2 Answers2

9

I think the error is in the code you did not include in your example: have you remembered to call import_array() in your module init function:

... this subroutine must also contain calls to import_array() and/or import_ufunc() depending on which C-API is needed. Forgetting to place these commands will show itself as an ugly segmentation fault (crash) as soon as any C-API subroutine is actually called.

http://docs.scipy.org/doc/numpy-1.10.1/user/c-info.how-to-extend.html#required-subroutine

I copied your example verbatim and added (using python 3)

PyMODINIT_FUNC
PyInit_numpytest(void)
{
    import_array();
    return PyModule_Create(&numpytest);
}

and the example ran without issues. Removing the call on the other hand produces a crash.

Ilja Everilä
  • 50,538
  • 7
  • 126
  • 127
0

A difference between MacOS and Linux

The following works fine for me on Linux:

PyMODINIT_FUNC PyInit_numpytest(void) {
    import_array();
    return PyModule_Create(&numpytest);
}

However, when using MacOS, I get the following error when trying to import the library:

SystemError: лy () method: bad call flags

The following works fine on both MacOS and Linux:

PyMODINIT_FUNC PyInit_numpytest(void) {
    PyObject* mod = PyModule_Create(&numpytest);
    import_array();
    return mod;
}

Notice that all I did was to change the order of PyModule_Create and import_array.

Tobias Bergkvist
  • 1,751
  • 16
  • 20