我无法实现这一目标。我所坚持的是试图将用C ++编写的模块暴露给嵌入式python解释器。
我使用的是boost :: python,但我不确定我应该为此做些什么,因为文档似乎缺乏,至少可以说。
我想要的是用BOOST_PYTHON_MODULE公开一些C ++代码,然后从同一个应用程序访问它。但是我无法导入它。我得到的,似乎最接近(只是相关部分):
#include <python/interpreter.hpp>
bp::object blag() {
return bp::str("Thingy");
}
BOOST_PYTHON_MODULE(modthingy) {
bp::def("blag", &blag);
}
Interpreter::Interpreter() {
Py_UnbufferedStdioFlag = 1;
Py_Initialize();
try {
init_module_modthingy();
} catch (bp::error_already_set) {
PyErr_Print();
}
main_module = bp::import("__main__");
main_namespace = main_module.attr("__dict__");
}
但是会打印错误AttributeError: 'NoneType' object has no attribute '__dict__'
我以后无法导入该模块。
这应该如何构建?
编辑: 好的,所以我得到的最接近的是接受答案中的一种方法:
PyImport_AppendInittab("modthingy", &PyInit_modthingy);
Py_Initialize();
然而,在我的情况下,这似乎并不特别有用,因为我希望能够在Initialize功能之后添加/导入模块。我将研究一些事情,即:
我将根据我的发现更新这篇文章。
答案 0 :(得分:1)
Boost.Python使用BOOST_PYTHON_MODULE
宏来定义Python模块初始化程序。生成的函数不是模块导入程序。这种差异类似于创建modthingy.py
模块并调用import modthingy
。
导入模块时,Python将首先检查模块是否为内置模块。如果模块不存在,那么Python将搜索module search path,试图根据模块名称查找python文件或库。如果找到了库,那么Python期望库提供一个初始化模块的函数。找到后,导入将在模块表中创建一个空模块,然后对其进行初始化。对于静态链接的模块,例如modthingy
,模块搜索路径将没有用,因为没有库可供查找。
对于嵌入,module table and initialization function文档声明对于静态模块,除非初始化表中有条目,否则不会自动调用模块初始化函数。对于Python 2和Python 3,可以通过在PyImport_AppendInittab()
:
Py_Initialize()
来实现此目的
BOOST_PYTHON_MODULE(modthingy)
{
// ...
}
PyImport_AppendInittab("modthingy", &initmodthingy);
Py_Initialize();
// ...
boost::python::object modthingy = boost::python::import("modthingy");
或者,对于Python 2,一旦初始化了解释器,就可以创建一个空模块,通过PyImport_AddModule()
添加到模块字典中,然后显式初始化模块。
BOOST_PYTHON_MODULE(modthingy)
{
// ...
}
Py_Initialize();
PyImport_AddModule("modythingy");
initmodthingy();
boost::python::object modthingy = boost::python::import("modthingy");
这种方法在官方Python嵌入式演示embed/demo.c中得到了证明。从BOOST_PYTHON_MODULE
创建的模块初始值设定项不会调用PyImport_AddModule()
,因此必须明确调用它。
另请注意,Python的C API用于在Python 2和3之间嵌入模块初始化函数的更改命名约定,因此对于BOOST_PYTHON_MODULE(modthingy)
,可能需要对Python 2使用&initmodthingy
和{3}的&PyInit_modthingy
。
这是一个最小的完整示例,演示了如何导入与嵌入式解释器静态链接的模块:
#include <iostream>
#include <string>
#include <boost/python.hpp>
std::string spam() { return "Spam spam spam"; }
BOOST_PYTHON_MODULE(example)
{
namespace python = boost::python;
python::def("spam", &spam);
}
int main()
{
// Add example to built-in.
PyImport_AppendInittab("example", &initexample);
// Start the interpreter.
Py_Initialize();
namespace python = boost::python;
try
{
// >>> import example
python::object example = python::import("example");
// >>> x = example.spam()
python::object x = example.attr("spam")();
// >>> print x
std::cout << "x = " << python::extract<std::string>(x)() << std::endl;
}
catch (const python::error_already_set&)
{
PyErr_Print();
}
}
输出:
x = Spam spam spam