boost::python::exec(anything) 调用时崩溃
Posted
技术标签:
【中文标题】boost::python::exec(anything) 调用时崩溃【英文标题】:Crash on call from boost::python::exec( anything ) 【发布时间】:2013-11-05 17:10:49 【问题描述】:我正在尝试在我的程序中实现一些 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
以进行链接以便编译。
想法?
【问题讨论】:
您能否详细说明这一点,或者最好提供sscce?你想在哪里调用boost::python::exec()
?
@TannerSansbury 在 int main() 中。它实际上是其中的第一行,程序在那一点上立即崩溃
嵌入 Python 时,解释器在调用 Boost.Python 之前需要初始化 (Py_Initialize()
)。您能否提供最少的 C++ 代码以及您的总体目标?目前尚不清楚正在尝试什么。你想嵌入 Python 吗? test_module
扩展的相关性是什么?
@TannerSansbury 我知道,我注意到在尝试使用 Python 的 C API 时,我失败了。我正在尝试嵌入 Python 并允许它使用上面的函数,这就是我根据 boost 的教程公开它的原因。请允许我使用 pastebin 以免使此页面混乱,请查看 pastebin.com/FHPmry9u
sscce 并不总是混乱的。在尝试调试代码时,它可能变得很有必要。最初发布的问题没有提到一些会使回答变得非常困难的关键细节。如果需要,请随时恢复编辑,但完整的问题可以避免链接失效,并且可能对未来的用户有所帮助。
【参考方案1】:
嵌入 Python 时,几乎所有对 Python 或 Boost.Python 的调用都应在使用 Py_Initialize()
初始化解释器之后发生。尝试在初始化之前调用解释器,例如使用boost::python::exec()
,将导致未定义的行为。
在确定崩溃源的同时,还有一些微妙的细节可以实现嵌入 Python 和模块的最终目标,然后让exec
导入嵌入的模块。
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
【讨论】:
"ImportError: No module named 'builtin'"。嗯。 @P.K.:Doh,看起来我是针对 Python 2 构建的。根据porting guide,__builtin__
模块在 Python 3 中被重命名为 builtins
。我会尝试找一些时间来针对 Python 3 重建并验证更改。
哦。好吧,我已经改变了它,但现在有一个导入错误。 Line 1, <string>, ___import___ not found
@P.K.:奇怪。我更改了导入(反映在上面的代码中),它适用于 Python 3.3.2。以上是关于boost::python::exec(anything) 调用时崩溃的主要内容,如果未能解决你的问题,请参考以下文章
无法使用 TSC - 读取文件“anything.ts”时出错:找不到文件
5 Ways to Learn and Remember Absolutely Anything