我正在尝试在程序中实现一些Python内容,因此决定使用Boost :: Python,因此我根据说明进行了编译,包括bjam,mingw / gcc,获取dll和.a文件。
我为此使用了Code :: Blocks,因此我将dll放在了我项目的工作目录中,我使用的其余dll都放在了该目录中,并决定运行boost::python::exec("b = 5");
立刻我崩溃了。有想法吗?
#include <boost/python.hpp>
float func(int a)
{
return a*a-0.5;
}
BOOST_PYTHON_MODULE(test_module)
{
using namespace boost::python;
def("func", func);
}
int main()
{
//Try one
boost::python::exec("b = 5");
//Crash
//Try two
Py_Initialize();
boost::python::exec("b = 5");
//Works fine
//Try three
Py_Initialize();
boost::python::exec("import test_module");
//Throws boost::python::error_already_set and crashes
/*
Something along the lines of
boost::python::exec("import test_module\n"
"var = test_module.func( 3 )\n");
*/
}
在项目的“构建选项”部分下,我添加了
libboost_python3-mgw48-d-1_54.dll
和libpython33
进行链接,以便进行编译。有想法吗?
最佳答案
嵌入Python时,几乎所有对Python或Boost.Python的调用都应该在使用Py_Initialize()
初始化了解释器之后进行。尝试在初始化之前调用解释器(例如,使用boost::python::exec()
)将导致未定义的行为。
虽然可以确定崩溃的根源,但仍有一些细微的细节可以实现实现嵌入Python和模块的最终目标,然后使exec
导入嵌入式模块。
导入模块时,Python将首先检查该模块是否为内置模块。如果该模块不是内置模块,则Python将尝试基于模块名称加载库,并期望该库提供将初始化该模块的功能。嵌入test_module
时,需要明确添加其初始化,以便import
在搜索内置模块时可以找到它。import
语句使用__import__
函数。此功能需要在exec
的全局变量中可用。
这是一个完整的示例,演示如何完成此操作:
#include <boost/python.hpp>
float func(int a)
{
return a*a-0.5;
}
BOOST_PYTHON_MODULE(test_module)
{
using namespace boost::python;
def("func", func);
}
// Use macros to account for changes in Python 2 and 3:
// - Python's C API for embedding requires different naming conventions for
// module initialization functions.
// - The builtins module was renamed.
#if PY_VERSION_HEX >= 0x03000000
# define MODULE_INIT_FN(name) BOOST_PP_CAT(PyInit_, name)
# define PYTHON_BUILTINS "builtins"
#else
# define MODULE_INIT_FN(name) BOOST_PP_CAT(init, name)
# define PYTHON_BUILTINS "__builtin__"
#endif
int main()
{
// Add the test_module module to the list of built-in modules. This
// allows it to be imported with 'import test_module'.
PyImport_AppendInittab("test_module", &MODULE_INIT_FN(test_module));
Py_Initialize();
namespace python = boost::python;
try
{
// Create an empty dictionary that will function as a namespace.
python::dict ns;
// The 'import' statement depends on the __import__ function. Thus,
// to enable 'import' to function the context of 'exec', the builtins
// module needs to be within the namespace being used.
ns["__builtins__"] = python::import(PYTHON_BUILTINS);
// Execute code. Modifications to variables will be reflected in
// the ns.
python::exec("b = 5", ns);
std::cout << "b is " << python::extract<int>(ns["b"]) << std::endl;
// Execute code using the built-in test_module.
python::exec(
"import test_module\n"
"var = test_module.func(b)\n",
ns);
std::cout << "var is " << python::extract<float>(ns["var"]) << std::endl;
}
catch (python::error_already_set&)
{
PyErr_Print();
}
}
执行后,其输出为:
b is 5
var is 24.5
关于c++ - boost::python::exec(任意)调用时崩溃,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19794760/