【问题标题】:Embedding Python into C - can't import method from python module将 Python 嵌入到 C 中 - 无法从 python 模块导入方法
【发布时间】:2019-07-19 08:53:10
【问题描述】:

我正在构建将使用 Python 插件的 C 应用程序。当尝试从另一个 Python 模块调用该方法时,函数 PyImport_ImportModule() 似乎正确导入了模块,然后我尝试使用 PyObject_GetAttrString() 从该模块获取函数,我得到的只是空。

我已经尝试使用PyModule_GetDict()PyDict_GetItemString()从模块中获取方法,但是效果是一样的。

main.c:

#include <stdio.h>
#include <python3.6/Python.h>

int main()
{
    PyObject *arg, *pModule, *ret, *pFunc, *pValue, *pMethod, *pDict;
    Py_Initialize();
    PyObject *sys = PyImport_ImportModule("sys");
    PyObject *path = PyObject_GetAttrString(sys, "path");
    PyList_Append(path, PyUnicode_FromString("."));

    pModule = PyImport_ImportModule("test");
    if(pModule == NULL)
    {
        perror("Can't open module");
    }
    pMethod = PyObject_GetAttrString(pModule, "myfun");
    if(pMethod == NULL)
    {
        perror("Can't find method");
    }

    ret = PyEval_CallObject(pMethod, NULL);
    if(ret == NULL)
    {
        perror("Couldn't call method");
    }

    PyArg_Parse(ret, "&d", pValue);
    printf("&d \n", pValue);

    Py_Finalize();
    return 0;
}

test.py:

def myfun():
  c = 123 + 123
  print('the result is: ', c)

myfun()

我得到的结果是:

Can't find method: Success
Segmentation fault (core dumped)

当我使用 gdb 调试器时,输出是:

pModule = (PyObject *) 0x7ffff5a96f48
pMethod = (PyObject *) 0x0

【问题讨论】:

  • 您的pMethodNULL,然后您仍然尝试调用它,这样会产生分段错误并使您的程序崩溃。您应该调试在那之前发生的事情。另外,不要使用perror:python C API 没有设置errno,所以使用perror 会得到无用的消息(实际上在这种情况下它会显示“成功”)。
  • 谢谢,但是段错误不是问题,而是后果。问题是,为什么 pMethod 是 NULL?在调用 pMethod 之前,我导入了给我“pModule = (PyObject *) 0x7ffff5a96f48”的模块,所以如果模块导入正确,为什么 pMethod 不存在? --> pMethod = (PyObject *) 0x0
  • PyObject_HasAttrString(pModule, "myfun") 返回什么?

标签: python c python-3.x import embedding


【解决方案1】:

您的程序没有运行,因为要导入的模块是test built-in module,而不是您的test.py 脚本。这是因为您将当前目录追加sys.path,因此在列表中每个其他已经存在的路径之后都会检查它。您应该将其插入到列表的开头,以便首先检查它。

这将起作用:

PyObject *sys = PyImport_ImportModule("sys");                                                                                                                                                                     
PyObject *path = PyObject_GetAttrString(sys, "path");                                                                                                                                                     
PyList_Insert(path, 0, PyUnicode_FromString("."));

顺便说一句,您应该先#include Python 标头,如文档中所述:

注意:由于 Python 可能会定义一些预处理器定义,这些定义会影响某些系统上的标准头文件,因此您必须在包含任何标准头文件之前包含 Python.h。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-31
    • 1970-01-01
    • 2022-01-22
    • 1970-01-01
    • 2013-08-01
    • 1970-01-01
    相关资源
    最近更新 更多