【发布时间】:2020-03-25 04:00:24
【问题描述】:
我正在尝试在 C++ 中导入一个模块;该模块位于一个包中,应该像这样访问:
from x.y import class1,func1, const1, etc
我使用的是 Python 3.6,对于这个版本,到目前为止我发现使用 PyRun_SimpleString 进行导入,然后使用 PyImport_AddModuleObject 处理我的模块。那就是:
PyRun_SimpleString("from PacKage1 import Module1 as Module1");
auto module = PyImport_AddModuleObject(PyUnicode_DecodeFSDefault("Module1"));
这样我就可以访问它的不同属性,如下所示:
auto args = Py_BuildValue("sOOOOONNiN", model_name, model_checkpoint_path, align_fn,
bank_folder_root, cache_folder, postfix,
rebuild_cache, use_jit, threshold, device);
if (module != nullptr) {
// dict is a borrowed reference.
auto pdict = PyModule_GetDict(module);
if (pdict == nullptr) {
cout << "Fails to get the dictionary.\n";
return 1;
}
//Py_DECREF(module);
PyObject *pKeys = PyDict_Keys(pdict);
PyObject *pValues = PyDict_Values(pdict);
map<string, string> my_map;
//cout << "size: " << PyDict_Size(pdict)<<endl;
char* cstr_key = new char[100];
char* cstr_value = new char[500];
for (Py_ssize_t i = 0; i < PyDict_Size(pdict); ++i) {
PyArg_Parse(PyList_GetItem(pKeys, i), "s", &cstr_key);
PyArg_Parse(PyList_GetItem(pValues, i), "s", &cstr_value);
//cout << cstr<< " "<< cstr2 <<endl;
my_map.emplace(cstr_key, cstr_value);
}
for (auto x : my_map)
{
cout << x.first << " : " << x.second << endl;
}
system("pause");
// Builds the name of a callable class
auto python_class = PyDict_GetItemString(pdict, "MyClass1");
system("pause");
if (python_class == nullptr) {
cout << "Fails to get the Python class.\n";
return 1;
}
//Py_DECREF(pdict);
cout << python_class;
PyObject* object;
// Creates an instance of the class
if (PyCallable_Check(python_class)) {
object = PyObject_CallObject(python_class, args);
Py_DECREF(python_class);
}
else {
std::cout << "Cannot instantiate the Python class" << endl;
Py_DECREF(python_class);
return 1;
}
auto val = PyObject_CallMethod(object, "is_jit_model_available", NULL);
if (!val)
cout << "error!";
cout << val;
当我尝试运行这段代码时,我得到了显示地图内容的输出:
size: 5
__doc__ : Module1
__loader__ : Module1
__name__ : Module1
__package__ : Module1
__spec__ : Module1
所以这是PyModule_GetDict(module);的结果但是,当涉及到从这个模块中提取类时,它失败了,即PyDict_GetItemString(pdict, "MyClass1");返回null。
在我看来,模块处理程序本身是不正确的,这可能是因为它可能没有指向实际模块,这意味着我在导入和获取该模块的句柄时完全失败。
因此,我想不出任何其他方式可以让我导入模块并像这样使用它。
我在这里错过了什么?
【问题讨论】:
-
您是否考虑过使用 C++ 框架来嵌入 Python?例如Boost Python(或其他)?这样的框架通常会更容易。
-
您在搜索选项时是否忽略了
PyImport_ImportModule? -
是的,但我的首要任务是尽可能不添加任何第三部分依赖项。
-
@user2357112supportsMonica 看过,可惜真的没看懂
-
PyObject *module = PyImport_ImportModule("packagename.submodulename");。你正在做的事情真的很奇怪并且没有你想要的效果 - 你正在为一个与你想要的完全无关的不存在的模块创建一个新的模块对象。
标签: python c++ python-embedding