在BOOST_Python_MODULE宏之外将C++实例传递到Python中
Passing a C++ instance into Python outside of BOOST_PYTHON_MODULE macro
我想将TestObj的一个实例从C++代码传递到python中。这里发布的代码在cout中产生错误:"没有为C++类型找到to_python(按值)转换器:class TestObj"。如果我将对象创建和main_module.attr("obj") = obj;
移动到BOOST_PYTHON_MODULE宏中,代码运行良好。
当我尝试传递带有或不带有boost::ptr的*TestObj
时,也会发生类似的情况。
testembed.py:
import sfgame
print("old x: " + str(obj.x))
obj.x = 10
print("new x: " + str(obj.x))
testobj.h
class TestObj{
public:
TestObj();
int x;
int getX();
void setX(int xv);
};
testobj.cpp
#include "TestObj.h"
TestObj::TestObj(){
}
int TestObj::getX(){
return x;
}
void TestObj::setX(int xv){
x = xv;
}
main.cpp
#include <boost/python.hpp>
#include "TestObj.h"
using namespace boost::python;
BOOST_PYTHON_MODULE(sfgame){
class_<TestObj>("TestObj")
.add_property("x", &TestObj::getX, &TestObj::setX)
;
}
int main(){
Py_Initialize();
object main_module = import("__main__");
object main_namespace = main_module.attr("__dict__");
TestObj obj;
try{
obj.setX(5);
main_module.attr("obj") = obj;
exec_file("testembed.py", main_namespace);
}
catch (const boost::python::error_already_set &){
PyObject *ptype, *pvalue, *ptraceback;
PyErr_Fetch(&ptype, &pvalue, &ptraceback);
std::string error;
error = boost::python::extract<std::string>(pvalue);
std::cout << error << std::endl;
}
system("PAUSE");
return 0;
}
通过Boost将C++对象传递给Python。无论调用Python的上下文如何,Python都有相同的先决条件:必须为C++对象的类型注册一个到Python的转换器。
创建boost::python::class_<T>
实例时,到Python和从Python的转换器会自动注册为类型T
。BOOST_PYTHON_MODULE
宏仅声明Python模块初始化函数,Python将在导入模块时调用该函数。在这种特殊情况下,可以通过在将TestObj
实例传递给Python之前执行以下任一操作来解决问题:
- 在
main()
中初始化解释器之后,通过class_
暴露TestObj
- 导入静态链接的
sfgame
模块。这需要通过PyImport_AppendInittab()
将模块初始化函数显式添加到Python初始化表中。有关详细信息,请参阅此答案
不建议直接调用模块初始化函数。当直接调用时,模块本身不会创建,但类型将在Boost.Python中注册。导入模块后,模块将被创建并初始化,从而再次注册类型。在Boost.Python的调试版本中,这将使断言失败,而在发布版本中,它将打印警告。
下面是一个完整的示例,演示在嵌入时将C++对象传递给Python。在该示例中,spam
类型在静态链接的example
模块内公开,而egg
类型在__main__
范围内公开。
#include <boost/python.hpp>
// Mockup models.
struct spam {};
struct egg {};
BOOST_PYTHON_MODULE(example)
{
namespace python = boost::python;
python::class_<spam>("Spam", python::init<>());
}
int main()
{
// Explicitly add initializers for staticly linked modules.
PyImport_AppendInittab("example", &initexample);
// Initialize Python.
Py_Initialize();
namespace python = boost::python;
try
{
// Create the __main__ module.
python::object main_module = python::import("__main__");
python::object main_namespace = main_module.attr("__dict__");
// Import the example module, this will cause the example module's
// initialization function to be invoked, registering the spam type.
// >>> import example
python::import("example");
// >>> spam = example.Spam()
spam spam;
main_namespace["spam"] = spam;
// Expose egg, defining it within the main module.
// >>> class Egg: pass
main_namespace["Egg"] = python::class_<egg>("Egg", python::init<>());
// >>> egg = Egg()
egg egg;
main_namespace["egg"] = egg;
// Verify variables and their types.
python::exec(
"import examplen"
"assert(isinstance(spam, example.Spam))n"
"assert(isinstance(egg, Egg))n",
main_namespace);
}
catch (const python::error_already_set&)
{
PyErr_Print();
return 1;
}
// Do not call Py_Finalize() with Boost.Python.
}
来自文档:
"此宏在使用它的作用域中生成两个函数:extern"C"void initname()和void init_module_name(),其主体必须在宏调用之后。"
您需要拨打initsfgame();
。
- 无法使用 SWIG 在 Python 中实例化C++类(获取属性错误)
- Python C API:如何检查对象是否是类型的实例
- 字节或整数地址预期,而不是str实例python 3
- swig c to python:抛出一个中止的实例后终止
- 如何使用 boost::p ython 创建和使用 Python 对象的实例
- 在python ctypes中截断了指向C++自定义类实例的指针地址
- 如何使用 SWIG 将 Python 类实例作为 C++ 函数的参数传递
- Python 可以运行脚本的多个实例,每个实例都包含自己的数据吗?
- 如何通过 Python/C API 将 Python 实例传递给 C++
- 用c++对象的全局实例扩展嵌入式python解释器
- boost python返回与makeconstructor相同的实例
- boost.python 解释器实例化
- 使用Boost::Python获取一个指向Python实例的c++指针
- 使用SWIG和Python/C API来包装一个函数,该函数采用C++类实例的Python列表
- 在BOOST_Python_MODULE宏之外将C++实例传递到Python中
- 实现具有自动增量实例属性的类的最python的方式是什么?
- 如何创建一个公共python函数,它可以接收c++结构体/实例或python对象作为参数
- 从Python中的另一个实例获取实例
- 向python嵌入式解释器公开c++类实例
- 如何从C++返回 Python 类型的实例