为什么在C+;中导入Python函数的模块后无法访问它+;?
我试图调用一个函数为什么在C+;中导入Python函数的模块后无法访问它+;?,python,c++,python-3.x,python-c-api,Python,C++,Python 3.x,Python C Api,我试图调用一个函数print\u stuff,该函数是C中用户定义的Python模块Spam中类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 */ P
print\u stuff
,该函数是C中用户定义的Python模块Spam
中类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;
}
\uuuu init\uuuuu.py
class Spam:
def __init__(self):
pass
def print_stuff(self):
print((1,2,3))
import Spam as Spam
当我运行C++代码时,我会得到以下错误:<代码> AtditError:'DICT '对象没有属性“PrrtTyStudio”< /Calp> < /P> 我尝试将从
PyModule_GetDict(pModule)
返回的字典内容作为字符串,并确认它没有提到函数
我在文档中查找了PyModule\u GetDict
,它返回的字典与在Python中调用模块时得到的字典相同。当我尝试调用Spam.\uuuuu dict\uuuuu
内部的\uuu init\uuuuuu.py
时,我得到了相同的结果,我的函数丢失了,但当我尝试Spam.Spam.\uuuu dict\uuuu
时,我得到了一个包含该函数的字典
因此,我决定将import语句从Spam import Spam更改为,以便Spam.\uu dict\uuuu
现在包含我的函数,它确实包含了这个函数。但是,运行C++代码时,没有什么变化。我仍然从字典中得到相同的错误,仍然无法调用我的函数
我确实想知道,在我的C++代码中,是否有一个类没有实例,所以我也尝试删除了周围类,并拥有<代码>垃圾邮件。Py <代码>只包含函数定义,然后导入,但是,同样,我也得到了同样的错误。
我有一种预感,这是某种名称空间问题,否则我不知道
PyModule\u GetDict
和\u dict\u\u
如何为同一个模块返回不同的字典,但老实说,我不知道从这里可以走到哪里
是我的类<代码>垃圾邮件<代码>不被认为是我试图从C++导入的模块的一部分吗?是我的C++代码> Pys<代码>缺少什么,或者我需要在C++中包含另一个语句,在导入模块后导入类,或者我没有正确导入模块?
我以前见过类似的问题,但它们往往出现在出现异常、搜索路径不正确或先决条件值返回NULL的情况下。我对C++有相当丰富的经验,但对Python和Python/C API的更新很新,虽然我已经阅读了涵盖API基本知识的文档,以及Python中的模块是如何工作的。 < P>首先,我不认为你需要SPAM.PY中最后两行。我把它简化为:
class Spam:
def __init__(self):
pass
def print_stuff(self):
print((1,2,3))
现在,让我们测试模块:
>>> import spam
>>> s = spam.Spam()
>>> s.print_stuff()
(1, 2, 3)
到目前为止,一切顺利。让我们看看我们是否可以从C++中使用它。以下是您的程序的工作版本:
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include <stdlib.h>
int main()
{
Py_Initialize();
//modify python module search path
auto modulePath = ".";
PyObject* sysPath = PySys_GetObject("path");
PyList_Append(sysPath, PyUnicode_FromString(modulePath));
PyObject* pModule = PyImport_ImportModule("spam");
PyObject* spam_class = PyObject_GetAttrString(pModule, "Spam");
if( !spam_class ) { PyErr_Print(); return EXIT_FAILURE; }
PyObject* spam = PyObject_CallObject(spam_class, NULL);
if( !spam ) { PyErr_Print(); return EXIT_FAILURE; }
PyObject* pFunc = PyObject_GetAttrString(spam, "print_stuff");
if (pFunc != NULL)
PyObject_CallObject(pFunc, NULL);
else
PyErr_Print();
return 1;
}
现在我们有了一个对象。它有一些方法,这些方法是属性,我们可以像往常一样通过PyObject\u GetAttrString
获得这些属性。其余的你都知道
我已经有几年没有使用过这种东西了,我的经验来自另一个方面,让Python可以访问C模块。我通过在Python解释器中使用dir
来实现上述示例,直到得到所需的内容。如果你“像翻译一样思考”,你可能会发现这一切更有意义。谢谢,这解决了问题,但我有几个问题。首先,我可能遗漏了一些东西,但您的spam.py版本似乎与我的版本相同,您的意思是init.py是不必要的吗?。其次,我的问题似乎是试图从模块字典中获取函数,而不是从模块中获取类,然后从类中获取函数。我认为类的成员函数对包含的模块实际上是不可见的,这是正确的吗?是的,afaik init.py是不必要的。至于“看不见”,不完全是。记住,Python对象在解释器执行类之前是不存在的。在那之前,它们只是一页纸上的文字。类定义是无生命的;它定义了实例能够做什么,但实例方法不属于该类。这听起来很奇怪,但是您首先执行类来创建一个实例。然后可以调用实例方法。
>>> s = spam.Spam()