2016-06-24 16 views
1

Ich habe versucht, ein Array von C nach Python übergeben und eine einfache arithmetische Operation numpy.prod durchzuführen, aber einen Segmentierungsfehler festgestellt. Könnte mir jemand helfen, aufzuzeigen, wo ich schief gelaufen bin? Vielen Dank!Python C API Segmentierungsfehler

#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(); 
} 

(ich folgte das Verfahren auf dieser Website http://blog.numerix-dsp.com/2013/08/how-to-pass-c-array-to-python-solution.html?m=1.)

+0

Ich sehe nicht, warum es einen segfault verursachen würde, aber die Argumente zu Ihrem 'PyArray_SimpleNewFromData()' Aufruf sehen falsch aus. 'array' ist ein Array von' double's, aber Sie verwenden den Typcode 'NPY_FLOAT32'. Sicherlich wollen Sie 'NPY_DOUBLE' oder (gleichwertig)' NPY_FLOAT64'. –

Antwort

0

Zusätzlich falsch Ihr Array-Objekt zu konstruieren, wie es in den Kommentaren beschrieben, wird das zweite Argument für Ihren PyObject_Call() Anruf falsch. Per its docs sollte das zweite Argument auf ein Tupel zeigen, das in Ihrem Fall Ihr Array-Objekt als einzelnes Element enthalten sollte, aber Sie übergeben das Array-Objekt selbst. Abhängig davon, wie sorgfältig diese Funktion oder vielleicht die aufgerufene Funktion ihre Argumente überprüft, könnte diese Nichtübereinstimmung leicht zu einem segfault führen.

Zusätzlich, wenn es keine Schlüsselwortargumente gibt, können Sie einfach ein Literal NULL als drittes Argument übergeben. In jedem Fall, da Sie sicher sein können, dass die Variable kwargsNULL ist, scheint es ein wenig sinnlos (wenn auch nicht fehlerhaft) zu Py_XDECREF() es.

+0

Beachten Sie, dass der Blogeintrag, den Sie verknüpft haben, den Aufbau eines Argumenttupels mit dem Arrayobjekt veranschaulicht. In dieser Hinsicht haben Sie es versäumt, dem Verfahren zu folgen. –

+0

Hallo! Vielen Dank für Ihre Vorschläge! Ich habe alle diese Teile bearbeitet, aber eine Ausgabe von "1" erhalten. Ich weiß nicht wirklich was passiert ist. (Ähnliche Dinge passiert gestern, als ich einfach den Wert meines Arrays gedruckt und bekam "1") – chemicaholic

+0

@chemicaholic, Also das Programm nicht mehr segfaults, ja? Dann habe ich die Frage beantwortet. Wenn Sie eine andere Frage zu dem überarbeiteten Code haben, stellen Sie ihn getrennt auf. Führen Sie außerdem einen Rollback für die Bearbeitung der Frage durch, in der Sie den gewünschten Code ändern. –