2016-06-07 109 views
-1

從閱讀另一個post,我想embbed一些一些Python代碼到C:Python嵌入使用C - 段錯誤

的main.c

#include <Python.h> 

int callModuleFunc(int array[], size_t size) { 
    PyObject *mymodule = PyImport_ImportModule("py_function"); 
    PyObject *myfunc = PyObject_GetAttrString(mymodule, "printlist"); 
    PyObject *mylist = PyList_New(size); 
    for (size_t i = 0; i != size; ++i) { 
     PyList_SET_ITEM(mylist, i, PyInt_FromLong(array[i])); 
    } 
    PyObject *arglist = Py_BuildValue("(o)", mylist); 
    PyObject *result = PyObject_CallObject(myfunc, arglist); 
    int retval = (int)PyInt_AsLong(result); 
    Py_DECREF(result); 
    Py_DECREF(arglist); 
    Py_DECREF(mylist); 
    Py_DECREF(myfunc); 
    Py_DECREF(mymodule); 
    return retval; 
} 

int main(int argc, char *argv[]) 
{ 
    int a[] = {1,2,3,4}; 
    callModuleFunc(a, 4); 
    return 0; 
} 

py_function.py

'''py_function.py - Python source designed to ''' 
'''demonstrate the use of python embedding''' 

def printlist(mylist): 
    print mylist 

然後我編譯:

gcc main.c -I/usr/include/python2.7 -lpython2.7 

但後來我跑的應用程序,它給了我一個分段錯誤:

/a.out 
[1] 18890 segmentation fault ./a.out 

有沒有辦法,我失去了一些東西?

+0

您從函數的返回值賦給了一大堆指針調用,但在使用它們之前不要檢查它們中的任何一個的有效性。你也可能混合了類型 - 你有沒有編譯警告? (雖然在C中即使缺少這些也並不意味着沒有這樣的問題)您也可以考慮在調試器下運行您的程序,然後使用backtrace命令或任何調試器調用它來檢查堆棧並查看失敗的位置發生。 –

回答

3

存在一些問題與您的代碼:

  1. Py_Initialize()不叫。
  2. PyImport_ImportModule()未能找到您的python文件,因爲在嵌入式Python中,您可以從開始,而不是初始模塊,相對於此模塊可以進行搜索。解決方法是明確包含當前目錄sys.path
  3. "(O)" in Py_BuildValue()應該使用大寫'O'
  4. printlist函數應返回一個值(因爲這是C代碼所期望的)。

這應該工作:

的main.c

#include <Python.h> 

void initPython() 
{ 
    Py_Initialize(); 
    PyObject *sysmodule = PyImport_ImportModule("sys"); 
    PyObject *syspath = PyObject_GetAttrString(sysmodule, "path"); 
    PyList_Append(syspath, PyString_FromString(".")); 
    Py_DECREF(syspath); 
    Py_DECREF(sysmodule); 
} 

int callModuleFunc(int array[], size_t size) { 
    PyObject *mymodule = PyImport_ImportModule("py_function"); 
    assert(mymodule != NULL); 
    PyObject *myfunc = PyObject_GetAttrString(mymodule, "printlist"); 
    assert(myfunc != NULL); 
    PyObject *mylist = PyList_New(size); 
    for (size_t i = 0; i != size; ++i) { 
     PyList_SET_ITEM(mylist, i, PyInt_FromLong(array[i])); 
    } 
    PyObject *arglist = Py_BuildValue("(O)", mylist); 
    assert(arglist != NULL); 
    PyObject *result = PyObject_CallObject(myfunc, arglist); 
    assert(result != NULL); 
    int retval = (int)PyInt_AsLong(result); 
    Py_DECREF(result); 
    Py_DECREF(arglist); 
    Py_DECREF(mylist); 
    Py_DECREF(myfunc); 
    Py_DECREF(mymodule); 
    return retval; 
} 

int main(int argc, char *argv[]) 
{ 
    initPython(); 

    int a[] = {1,2,3,4,5,6,7}; 
    callModuleFunc(a, 4); 
    callModuleFunc(a+2, 5); 

    Py_Finalize(); 
    return 0; 
} 

py_function.py

'''py_function.py - Python source designed to ''' 
'''demonstrate the use of python embedding''' 

def printlist(mylist): 
    print mylist 
    return 0 
+0

你好萊昂,它的作品。現在,我嘗試在Python源代碼中添加numpy,但它給了我:'main.c:18:callModuleFunc:Assertion'mymodule!=((void *)0)'failed'。當我用Python導入其他庫時,你知道我的C代碼需要做什麼嗎? – FacundoGFlores

+1

你在'py_function.py'中導入numpy嗎?當你直接用python運行'py_function.py'時,它的工作沒有問題嗎?如果是這樣,那麼問題可能通過正確填充'sys.path'來解決。 – Leon

+0

python模塊在我的C程序之外正常工作。 「正確填充sys.path」是什麼意思?我看到下面的例子:https://github.com/Frogee/PythonCAPI_testing/blob/master/testEmbed.cpp,並且在上面的例子中,他似乎沒有放置任何東西,只是「sys」模塊。 – FacundoGFlores