1

I was trying to pass an array from C to python and perform a simple arithmetic operation numpy.prod, but encountered a segmentation error. Could anybody help me point out where went wrong? Thank you!

#include <Python.h>
#include <stdio.h>
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
#include "/share/apps/anaconda2/pkgs/numpy-1.10.4-py27_1/lib/python2.7/site-packages/numpy/core/include/numpy/arrayobject.h"

double Array[4] = {1.0, 2.0, 3.0, 4.0};

double call_func(PyObject *func, double array[]){
        PyObject *args;
        PyObject *kwargs;
        PyObject *result;
        npy_intp dims[1] = {4};
        double retval;

        PyGILState_STATE state = PyGILState_Ensure();

        if (!PyCallable_Check(func)){
                printf("%s", "Function is not callable!\n");
        }

        args = PyArray_SimpleNewFromData(1, dims, NPY_FLOAT32, array);
        kwargs = NULL;

        result = PyObject_Call(func, args, kwargs);
        Py_DECREF(args);
        Py_XDECREF(kwargs);

        if (PyErr_Occurred()){
                PyErr_Print();
        }

        if (!PyFloat_Check(result)){
                printf("%s", "Callable did not return a float!");
        }

        retval = PyFloat_AsDouble(result);
        Py_DECREF(result);

        PyGILState_Release(state);
        return retval;
}

PyObject *import_name(const char *modname, const char *symbol){
        PyObject *mymodule = PyImport_ImportModule(modname);
        return PyObject_GetAttrString(mymodule, symbol);
}

void main(){
        PyObject *myfunc;
        double retval;

        import_array();

        Py_Initialize();

        myfunc = import_name("numpy", "prod");

        retval = call_func(myfunc, Array);
        Py_DECREF(myfunc);

        printf("%d\n", retval);

        Py_Finalize();
}

(I followed the procedure on this website http://blog.numerix-dsp.com/2013/08/how-to-pass-c-array-to-python-solution.html?m=1.)

snsunx
  • 155
  • 1
  • 9
  • I don't see why it would cause a segfault, but the arguments to your `PyArray_SimpleNewFromData()` call look wrong. `array` is an array of `double`s, but you use type code `NPY_FLOAT32`. Surely you want `NPY_DOUBLE` or (equivalent) `NPY_FLOAT64`. – John Bollinger Jun 24 '16 at 18:01

1 Answers1

0

In addition to constructing your array object wrongly, as described in comments, the second argument to your PyObject_Call() call appears wrong. Per its docs, the second argument should point to a tuple, which in your case should contain your array object as its single element, but you pass the array object itself. Depending on how carefully that function or maybe the called function checks its arguments, that mismatch could easily cause a segfault.

Additionally, if there are no keyword args then you can just pass a literal NULL as the third argument. In any case, since you can be certain that variable kwargs is NULL, it seems a bit pointless (albeit not erroneous) to Py_XDECREF() it.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
  • Note that the blog entry you linked demonstrates building an argument tuple containing the array object. In this respect you failed to follow the procedure it gives. – John Bollinger Jun 24 '16 at 18:14
  • Hi! Thank you for your suggestions! I have edited all those parts but got an output of "1". I don't really know what happened. (Similar things happened yesterday when I simply printed the value of my array and got "1") – snsunx Jun 24 '16 at 18:57
  • @chemicaholic, So the program no longer segfaults, yes? Then I have answered the question. If you have a different question about the revised code then pose it separately. Also, roll back the edit of the question in which you change the code you are asking about. – John Bollinger Jun 24 '16 at 19:19
  • @chemicaholic, but for what it's worth, it looks like your new problem is simply in the way that you display the result. The field descriptor `%d` is for a corresponding argument of type `int`, but you provide a `double`. You want the `%f` field descriptor for that. – John Bollinger Jun 24 '16 at 20:02
  • It works now! The problem is just with the `%d`. Thank you so much! – snsunx Jun 24 '16 at 20:04