首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Boost.Python(一)

小编将Boost.Python官方文档的内容梳理补充给大家,细节详见官方文档。

The Boost Python Library is a framework for interfacing Python and C++. It allows you to quickly and seamlessly expose C++ classes functions and objects to Python, and vice-versa, using no special tools -- just your C++ compiler. It is designed to wrap C++ interfaces non-intrusively, so that you should not have to change the C++ code at all in order to wrap it, making Boost.Python ideal for exposing 3rd-party libraries to Python.

The library's use of advanced metaprogramming techniques simplifies its syntax for users, so that wrapping code takes on the look of a kind of declarative interface definition language (IDL).

The Boost.Python‘s compile need MSVC and Python.

C++:

#include

#include

using namespace std;

char const * greet()

{

return"hello,world";

}

BOOST_PYTHON_MODULE(hello_ext)

{

using namespace boost::python;

def("greet",greet);

}

python:

importhello_ext

printhello_ext.greet()

Here, we wrote a C++ class wrapper that exposes the member functions greet and set. Now, after building our module as a shared library, we may use our class World in Python.

#include

#include

using namespace std;

struct World

{

voidset(string msg) { this->msg = msg; }

string greet() {returnmsg; }

string msg;

};

BOOST_PYTHON_MODULE(hello)

{

using namespace boost::python;

class_("World")

.def("greet",&World::greet)

.def("set", &World::set);

}

C++:

#include

#include

using namespace std;

struct World

{

World(string msg):msg(msg){}

World(double a,double b):a(a),b(b) {}

voidset(string msg) { this->msg = msg; }

string greet() {returnmsg; }

double sum_s() {returna + b; }

string msg;

double a;

double b;

};

BOOST_PYTHON_MODULE(hello)

{

using namespace boost::python;

class_("World",init())

.def(init())

.def("greet",&World::greet)

.def("set",&World::set)

.def("sum_s",&World::sum_s);

}

Python:

importhello

planet = hello.World(5,6)

planet2 = hello.World("hollo world")

printplanet.sum_s()

printplanet2.greet()

init() exposes the constructor taking in a std::string (in Python, constructors are spelled ""__init__"").

On the other hand, if we do not wish to expose any constructors at all, we may use no_init instead:

class_("Abstract",no_init)

#include

#include

using namespace std;

struct Var

{

Var(string name):name(name),value(){}

string const name;

floatvalue;

};

BOOST_PYTHON_MODULE(hello_var)

{

using namespace boost::python;

class_("Var",init())

.def_readonly("name",&Var::name)

.def_readwrite("value",&Var::value);

}

Data members may also be exposed to Python so that they can be accessed as attributes of the corresponding Python class. Each data member that we wish to be exposed may be regarded as read-only or read-write.

C++:

#include

#include

using namespace std;

struct Num

{

Num(){}

floatget() const {returnval; }

voidset(floatval) { this->val = val; }

floatval;

};

BOOST_PYTHON_MODULE(hello_num)

{

using namespace boost::python;

class_("Num")

.add_property("rovalue",&Num::get)

.add_property("value",&Num::get,&Num::set);

}

python:

>>> x = Num()

>>> x.value =3.14

>>> x.value,x.rovalue

(3.14,3.14)

>>> x.rovalue =2.17# error!

In C++, Well designed classes that take advantage of encapsulation hide the class' data members. The only way to access the class' data is through access (getter/setter) functions.

However, in Python attribute access is fine; it doesn't neccessarily break encapsulation to let users handle attributes directly, because the attributes can just be a different syntax for a method call.

C++:

#include

#include

#include

using namespace std;

struct Base

{

virtual ~Base() {};

virtual string getName() {return"Base"; }

stringstr;

};

struct Derived : Base

{

string getName() {return"Derived"; }

};

void b(Base *base) { cout getName()

void d(Derived *derived) { cout getName()

Base* factory() {returnnew Derived; }

BOOST_PYTHON_MODULE(hello_derived)

{

using namespace boost::python;

//wrap the baseclassBase

class_("Base")

.def("getName",&Base::getName)

.def_readwrite("str",&Base::str);

//wrap theclasshierarchies Derivedand

//inform Boost.Python of the inheritance relationship between Derivedandits baseclassBase.

class_ >("Derived")

.def("getName",&Derived::getName)

.def_readwrite("str",&Derived::str);

def("b",b);

def("d",d);

//use return_value_policy to instruct Python to adopt the pointer to Base

//andhold the instanceina new Python Baseobjectuntil the the Pythonobjectisdestroyed.

def("factory",factory,return_value_policy());

}

python:

importhello_derived

derive = hello_derived.factory()

hello_derived.d(derive)

One of the goals of Boost.Python is to be minimally intrusive on an existing C++ design. In principle, it should be possible to expose the interface for a 3rd party library without changing it. It is not ideal to add anything to our class Base. Yet, when you have a virtual function that's going to be overridden in Python and called polymorphically from C++, we'll need to add some scaffoldings to make things work properly. What we'll do is write a class wrapper that derives from Base that will unintrusively hook into the virtual functions so that a Python override may be called:

struct Base

{

virtual ~Base() {}

virtualintf() =;

};

struct BaseWrap : Base,wrapper

{

intf()

{

returnthis->get_override("f")();

}

};

We've seen in the previous section how classes with pure virtual functions are wrapped using Boost.Python'sclass wrapperfacilities. If we wish to wrap non-pure-virtual functions instead, the mechanism is a bit different.

C++:

//类的虚函数,实现的功能是:可以编写Python类,来继承C++类

#include

#include

#include

#include

using namespace boost::python;

using namespace std;

struct Base

{

virtual ~Base() {}

virtualintf() {return; };

};

struct BaseWrap : Base,wrapper

{

intf()

{

if(override f = this->get_override("f"))

returnf(); //如果函数进行重载了,则返回重载的

returnBase::f(); //否则返回基类的

}

intdefault_f() {returnthis->Base::f(); }

};

BOOST_PYTHON_MODULE(hello_virtual)

{

class_("Base")

.def("f",&Base::f,&BaseWrap::default_f);

}

python:

importhello_virtual

base = hello_virtual.Base()

# 定义派生类,继承C++类

classDerived(hello_virtual.Base):

deff(self):

return42

derived = Derived()

printbase.f()

printderived.f()

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20181231G17O4A00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券