2016-06-24 81 views
1

我試圖從C傳遞數組到python並執行簡單的算術運算numpy.prod,但遇到了分段錯誤。有誰能幫我指出哪裏出了問題?謝謝!Python C API分段錯誤

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

(我跟着這個網站http://blog.numerix-dsp.com/2013/08/how-to-pass-c-array-to-python-solution.html?m=1。在程序)

+0

我不明白爲什麼它會導致段錯誤,但是你的'PyArray_SimpleNewFromData()'調用的參數看起來是錯誤的。 'array'是一個'double'數組,但是你使用類型代碼'NPY_FLOAT32'。當然你想'NPY_DOUBLE'或(等同)'NPY_FLOAT64'。 –

回答

0

除了錯誤地構建您的數組對象,如評論所描述的,第二個參數的PyObject_Call()通話出現錯誤。每its docs,第二個參數應該指向一個元組,在你的情況下應該包含你的數組對象作爲它的單個元素,但你傳遞數組對象本身。根據這個函數的細緻程度或被調用的函數檢查它的參數,這種不匹配很容易導致段錯誤。

此外,如果沒有關鍵字參數,那麼您可以傳遞一個文字NULL作爲第三個參數。在任何情況下,因爲你可以確定變量kwargsNULL,它似乎有點沒有意義(儘管沒有錯誤),Py_XDECREF()它。

+0

請注意,您鏈接的博客條目演示了構建包含數組對象的參數元組。在這方面,你沒有遵循它提供的程序。 –

+0

嗨!謝謝你的建議!我編輯了所有這些部分,但得到了「1」的輸出。我真的不知道發生了什麼事。 (類似的事情昨天發生時,我簡單地打印了我的數組的值,並得到「1」) – chemicaholic

+0

@chemicaholic,所以程序不再segfaults,是嗎?然後我回答了這個問題。如果您對修改後的代碼有不同的問題,請單獨提出。另外,回滾你修改你詢問的代碼的問題的編輯。 –