将C++的类转换为python
参考链接:https://www.boost.org/doc/libs/1_65_1/libs/python/doc/html/tutorial/index.html
成员函数
参考链接:https://www.boost.org/doc/libs/1_65_1/libs/python/doc/html/tutorial/tutorial/exposing.html
struct World
{
void set(std::string msg) { this->msg = msg; }
std::string greet() { return msg; }
std::string msg;
};
包装成Python可调用函数
#include <boost/python.hpp>
using namespace boost::python;
BOOST_PYTHON_MODULE(hello)
{
class_<World>("World")
.def("greet", &World::greet)
.def("set", &World::set)
;
}
构造函数
struct World
{
World(std::string msg): msg(msg) {} // added constructor
World(double,double);
void set(std::string msg) { this->msg = msg; }
std::string greet() { return msg; }
std::string msg;
};
python的构造函数使用的是__init__,因此使用init来致命是类的构造函数
class_<World>("World", init<std::string>())
.def(init<double, double>())
.def("greet", &World::greet)
.def("set", &World::set)
;
如果不想暴露类的构造函数,则使用class(“Abstract”, no_init)
,任何调用其构造函数都会报错,可以用在接口类中_
成员变量
struct Var
{
Var(std::string name) : name(name), value() {}
std::string const name;
float value;
};
成员函数
class_<Var>("Var", init<std::string>())
.def_readonly("name", &Var::name)
.def_readwrite("value", &Var::value);
类的属性
在c++中,成员变量具有不同的属性,但是在python中可以访问任何成员变量。如果向访问C++类中的成员变量,则需要通过getter和sertter函数。
struct Num
{
Num();
float get() const;
void set(float value);
...
};
封装
class_<Num>("Num")
.add_property("rovalue", &Num::get)
.add_property("value", &Num::get, &Num::set);
>>> x = Num()
>>> x.value = 3.14
>>> x.value, x.rovalue
(3.14, 3.14)
>>> x.rovalue = 2.17 # error!
继承
以上的例子是对非多态类的封装,对于多态类的封装如下
struct Base { virtual ~Base(); };
struct Derived : Base {};
void b(Base*);
void d(Derived*);
Base* factory() { return new Derived; }
对于继承,则需指明继承对象;对于factory()返回派生类,则需要使用return_value_policy<manage_new_object>来让一个基类指针指向派生类指针。
对于
class_<Base>("Base")
class_<Derived, bases<Base> >("Derived")
def("b", b);
def("d", d);
def("factory", factory,return_value_policy<manage_new_object>());
普通函数
参考链接:https://www.boost.org/doc/libs/1_65_1/libs/python/doc/html/tutorial/tutorial/functions.html#tutorial.functions.default_arguments.boost_python_member_function_ove
对于C++来说会操作指针和引用等低级原语,在变成Python可调用是需要指明这些对象的周期。
X& f(Y& y, Z* z)
{
y.z = z;
return y.x;
}
1,2是参数的位置
def("f", f,return_internal_reference<1,with_custodian_and_ward<1, 2> >());
使用的政策是:
policy1<args...,
policy2<args...,
policy3<args...> > >
policy | 说明 |
---|---|
with_custodian_and_ward | Ties lifetimes of the arguments |
with_custodian_and_ward_postcall | Ties lifetimes of the arguments and results |
return_internal_reference | Ties lifetime of one argument to that of result |
return_value_policy | with T one of |
reference_existing_object | naive (dangerous) approach |
copy_const_reference | Boost.Python v1 approach |
copy_non_const_reference | |
manage_new_object | Adopt a pointer and hold the instance |
重载
struct X
{
bool f(int a)
{
return true;
}
bool f(int a, double b)
{
return true;
}
bool f(int a, double b, char c)
{
return true;
}
int f(int a, int b, int c)
{
return a + b + c;
};
};
bool (X::*fx1)(int) = &X::f;
bool (X::*fx2)(int, double) = &X::f;
bool (X::*fx3)(int, double, char)= &X::f;
int (X::*fx4)(int, int, int) = &X::f;
.def("f", fx1)
.def("f", fx2)
.def("f", fx3)
.def("f", fx4)
也可以自动重载具有相同序列参数的函数
void foo()
{
/*...*/
}
void foo(bool a)
{
/*...*/
}
void foo(bool a, int b)
{
/*...*/
}
void foo(bool a, int b, char c)
{
/*...*/
}
BOOST_PYTHON_FUNCTION_OVERLOADS(foo_overloads, foo, 0, 3)
.def("foo", (void(*)(bool, int, char))0, foo_overloads());
默认参数
int f(int, double = 3.14, char const* = "hello");
手工
// write "thin wrappers"
int f1(int x) { return f(x); }
int f2(int x, double y) { return f(x,y); }
/*...*/
// in module init
def("f", f); // all arguments
def("f", f2); // two arguments
def("f", f1); // one argument
自动
BOOST_PYTHON_FUNCTION_OVERLOADS(f_overloads, f, 0, 2)//0-2个默认参数
def("f", f, f_overloads());
对于类中的成员函数
struct george
{
void
wack_em(int a, int b = 0, char c = 'x')
{
/*...*/
}
};
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(george_overloads, wack_em, 1, 3)
.def("wack_em", &george::wack_em, george_overloads());