【问题标题】:Embedding Python in C - Segfault在 C 中嵌入 Python - 段错误
【发布时间】:2016-06-07 19:30:06
【问题描述】:

通过阅读另一个post,我正在尝试将一些 Python 代码嵌入到 C 中:

ma​​in.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

我有什么遗漏的吗?

【问题讨论】:

  • 您从函数调用的返回值中分配了一大堆指针,但在使用它们之前不要检查它们的有效性。您可能还会混淆类型 - 您是否收到任何编译警告? (尽管在 C 中,即使没有这样的问题并不意味着没有这样的问题)您也可以考虑在调试器下运行程序,然后使用 backtrace 命令或调试器调用的任何命令来检查堆栈并查看失败的位置发生了。

标签: python c segmentation-fault


【解决方案1】:

您的代码有几个问题:

  1. Py_Initialize() 未被调用。
  2. PyImport_ImportModule() 找不到您的 python 文件,因为在嵌入式 Python 中,您启动 没有 一个初始模块,相对于它可以进行搜索。解决方法是在 sys.path 中显式包含当前目录。
  3. "(O)"Py_BuildValue() 中应使用大写字母'O'
  4. printlist 函数应该返回一个值(因为这是 C 代码所期望的)。

这应该可行:

ma​​in.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

【讨论】:

  • 你好 Leon,它有效。现在,我尝试在 python 源代码中添加 numpy,但它给了我:` main.c:18: callModuleFunc: Assertion mymodule != ((void *)0)' failed。当我在 Python 中导入其他库时,你知道我的 C 代码需要做什么吗?
  • 你在py_function.py 中加入了import numpy 吗?当你直接用 python 运行py_function.py 时它是否正常工作?如果是这样,那么问题很可能通过正确填充sys.path 来解决。
  • python 模块在我的 C 程序之外正常工作。 “正确填充 sys.path”是什么意思?我看到以下示例:github.com/Frogee/PythonCAPI_testing/blob/master/testEmbed.cpp 并且他似乎没有放置任何其他内容,而是您在上面的示例中放置的“sys”模块。
  • 我最初的解决方案包含与 stackoverflow.com/questions/7624529/… 相同的错误。我按照answer 对那个问题进行了修复。
  • 我认为您在np.array(mylyst, dtype=np.float32) 中拼错了mylist。在嵌入式 python 环境中尝试之前,请在常规 python 环境中测试您的 python 代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-01-28
  • 1970-01-01
  • 1970-01-01
  • 2012-02-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多