【发布时间】:2021-07-01 14:55:55
【问题描述】:
我正在尝试从 C++ 中用户定义的 Python 模块 Spam 调用一个函数 print_stuff,它是类 Spam 的成员
#define PY_SSIZE_T_CLEAN
#include <Python.h>
int main()
{
Py_Initialize();
//modify python module search path
auto modulePath = /* hardcoded search path for module */
PyObject* sysPath = PySys_GetObject("path");
PyList_Append(sysPath, PyUnicode_FromString(modulePath));
PyObject* pModule = PyImport_ImportModule("Spam");
PyObject* pDict = PyModule_GetDict(pModule);
PyObject* pFunc = PyObject_GetAttrString(pDict, "print_stuff");
if (pFunc != NULL)
PyObject_CallObject(pFunc, NULL);
else
PyErr_Print();
return 1;
}
我的 Python 模块由 2 个文件组成; Spam.py 和 __init__.py 都位于同一目录 /Spam 这是包含我的 VS 解决方案和 C++ 代码的目录的子文件夹。
Spam.py
class Spam:
def __init__(self):
pass
def print_stuff(self):
print((1,2,3))
__init__.py
import Spam as Spam
当我运行我的 C++ 代码时,我收到以下错误:AttributeError: 'dict' object has no attribute 'print_stuff'
我尝试获取从PyModule_GetDict(pModule) 返回的字典内容作为字符串,并确认它没有提及该函数。
我查找了 PyModule_GetDict 的文档,它说它返回的字典与您在 Python 中的模块上调用 __dict__ 时返回的字典相同。当我尝试在__init__.py 中调用Spam.__dict__ 时,我得到了相同的结果,我的函数丢失了,但是当我尝试Spam.Spam.__dict__ 时,我得到了一个包含该函数的字典。
据此,我决定将 import 语句更改为 from Spam import Spam,以便 Spam.__dict__ 现在包含我的函数,它确实做到了。但是,当我运行我的 C++ 代码时,没有任何变化。我的字典仍然出现同样的错误,并且仍然无法调用我的函数。
我确实想知道这是否是我的 C++ 代码中没有类的实例的问题,所以我也尝试删除周围的类并让 Spam.py 只包含函数定义然后导入它,但是,再次,我得到了同样的错误。
我有预感这是某种命名空间问题,否则我看不出 PyModule_GetDict 和 __dict__ 如何为同一个模块返回不同的字典,但老实说我不知道从哪里开始.
我的课程Spam 不被视为我尝试从 C++ 导入的模块的一部分吗?我的__init__.py 是否遗漏了某些内容,或者我可能需要在 C++ 中包含另一个语句来在我导入模块后导入类,或者我一开始就没有正确导入模块?
我以前见过类似的问题,但它们往往出现在引发异常、搜索路径不正确或先决条件值返回 NULL 的情况下。我对 C++ 相当有经验,但对 Python 还是很陌生,对 Python/C API 还是比较陌生,尽管我已经阅读了涵盖 API 基础知识以及模块如何在 Python 中工作的文档。
【问题讨论】:
标签: python c++ python-3.x python-c-api