我有一个用C ++编写的内部库,目前正在研究将其扩展到Python中。我在开始时就考虑了Boost.Python,但是我愿意接受其他选择。
当前,我有一个C ++函数,需要接受一个Python类实例,然后使用该对象的方法执行某些任务。这个想法是让Python用户永远不需要处理C ++。期望他们从我将提供的Python模板/示例类中创建此Python对象,并使用我可以假设在C ++库中存在的预设方法名称。
暴露给Python用户的界面如下所示:
class Foo(object):
def __init__(self, args):
"""create an instance of this class with instance-specific attributes"""
def Bar1(self, a, b, c):
"""do something with the given integers a, b and c"""
pass
def Bar2(self, a, b, c):
"""do something else with the given integers a, b and c"""
pass
import mylib
cheese = mylib.Wine()
cheese.do_something(Foo)
Run Code Online (Sandbox Code Playgroud)
在C ++中,相应的代码如下所示:
#include <boost/python.h>
#include <Python.h>
class Wine {
public:
Wine() {};
~Wine() {};
static void do_something(boost::python::object *Foo) {
int a = 1;
int b = 2;
int c = 3;
Foo->attr("Bar1")(a, b, c);
Foo->attr("Bar2")(a, b, c);
};
};
BOOST_PYTHON_MODULE(mylib)
{
using namespace boost::python;
class_<Wine>("Wine")
.def("do_something", &Wine::do_something);
};
Run Code Online (Sandbox Code Playgroud)
我已经成功地编译了此代码,并验证了名为Wine的C ++类确实适用于Python,并且可以访问其成员函数。如果我编写了一个成员函数“ greet()”,该成员函数仅返回“ Hello,world!”,那么它将很好地工作。
我在这里需要强调传递Foo实例的重要性。我没有办法简单地将Foo模块导入C ++代码并在C ++中创建Foo实例。我要从Python用户接收的对象具有我需要使用的属性,该属性特定于实例,而不是类本身。
问题是我无法弄清楚如何将Python实例传递到do_something中,以使其在C ++中作为可调用的boost :: python :: object出现。上面的代码返回以下C ++签名不匹配错误:
Boost.Python.ArgumentError: Python argument types in
Wine.do_something(Wine, Foo)
did not match C++ signature:
do_something(boost::python::api::object*)
Run Code Online (Sandbox Code Playgroud)
仔细阅读互联网的答案两天没有取得任何进展。关于如何将C ++类传递到Python中似乎有很多信息,但是我找不到相反方向的信息。非常感谢您在这里提供一些指导。
谢谢!
初始代码有两个错误:
self和 的一个实例Foo)传递给Wine::do_something()只接受一个参数的静态C++ 函数。为了解决这个问题,在暴露Wine类时,Wine.do_something()需要通过boost::python::class_::staticmethod()成员函数将 Python成员函数设置为静态。当作为静态方法公开时,Boost.Python 将不再传递self实例参数。PyObject*) 不同,Boost.Python 提供了一个boost::python::object通常通过值或引用传递的更高级别的表示法类。在内部,此类与为boost::python::handle执行智能指针管理的 进行交互PyObject。这是基于原始代码的完整 Python 扩展:
#include <boost/python.hpp>
class Wine
{
public:
static void do_something(boost::python::object object)
{
int a = 1;
int b = 2;
int c = 3;
object.attr("Bar1")(a, b, c);
object.attr("Bar2")(a, b, c);
};
};
BOOST_PYTHON_MODULE(example)
{
namespace python = boost::python;
python::class_<Wine>("Wine")
.def("do_something", &Wine::do_something)
.staticmethod("do_something")
;
};
Run Code Online (Sandbox Code Playgroud)
互动使用:
>>> class Foo(object):
... def Bar1(self, a, b, c):
... print "Bar1", locals()
... def Bar2(self, a, b, c):
... print "Bar2", locals()
...
>>> import example
>>> cheese = example.Wine()
>>> cheese.do_something(Foo())
Bar1 {'a': 1, 'c': 3, 'b': 2, 'self': <__main__.Foo object at 0xb6b0f2ac>}
Bar2 {'a': 1, 'c': 3, 'b': 2, 'self': <__main__.Foo object at 0xb6b0f2ac>}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3039 次 |
| 最近记录: |