2016-06-07 110 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