Use some simple examples to note common usage.
Export module
Export an empty Python module,
BOOST_PYTHON_MODULE(py_sample) {
}
Copy the code
You can dir the contents of the exported module in the corresponding Python code,
import py_sample
print dir(py_sample) # ['__doc__', '__name__', '__package__']
Copy the code
The export function
Define functions in C++ and export them accordingly,
std::string Foobar() {
return "foobar";
}
BOOST_PYTHON_MODULE(py_sample) {
def("foobar", Foobar);
}
Copy the code
For function arguments and return value is a simple type, such as int/long/float/double/Boolean, string, etc., the Boost will automatically be transformed.
Derived classes
To get straight to a specific example,
class Base {
public:
Base(std::string name):
name_(name),
value1_(0),
value2_(0) {
}
Base(int value1, int value2): name_("") {
value1_ = value1;
value2_ = value2;
}
std::string GetName() {
return name_;
}
int getValue2() {
return value2_;
}
public:
std::string name_;
int value1_;
private:
int value2_;
};
BOOST_PYTHON_MODULE(py_sample) {
class_<Base>("Base", init<std::string>())
.def(init<int, int>())
.def("get_name", &Base::GetName)
.def_readonly("value1", &Base::value1_)
.add_property("value2", &Base::getValue2)
;
}
Copy the code
Constructor derivation
For constructors, if only one constructor exists, the class name is followed by the init block. If multiple constructors exist, the rest of the constructors begin with.def(init<… >()) to export.
Member function export
For functions, export via def operation.
Member variable export
For public fields, you can export them by def_readonly or def_readwrite. For private fields, you need to export them by add_property and provide corresponding getter/setter interfaces.
Inheritance relationship treatment
C++ class Base* (Base*); Base* (Base*);
class Child: public Base {
public:
Child(std::string name):
Base(name) {
}
};
void Process(Base* base) {
}
BOOST_PYTHON_MODULE(py_sample) {
...
class_<Child>("Child", init<std::string>())
;
def("process", &Process);
}
Copy the code
The above export loses inheritance in Python and cannot pass the Child instance to the Process function,
from py_sample import Base, Child, process
instance = Child("child")
print isinstance(instance, Child), isinstance(instance, Base) # True, False
Copy the code
The call,
process(instance);
Copy the code
The following exception occurs,
Boost.Python.ArgumentError: Python argument types in
py_sample.process(Child)
did not match C++ signature:
process(class Base *)
Copy the code
In order to handle the inheritance relationship of the exported class, you need to display the base class when exporting the class.
class_<Child, bases<Base>>("Child", init<std::string>())
;
Copy the code
The isinstance judgment above returns the expected result and process can be called normally.
Inherit exported classes in Python
If you define a pure virtual or virtual function in a C++ class and want to inherit the class from Python and override the corresponding function, you need to use wrapper.
class Base { public: Base(): value_(0) { } virtual int GetValue() = 0; virtual int Multiple(int v) { return value_ * v; } int TryGetValue() { return GetValue(); } int TryMultiple(int v) { return Multiple(v); } private: int value_; }; class BaseWrap: public Base, public wrapper<Base> { public: int GetValue() { return this->get_override("get_value")(); } int Multiple(int v) { if (override f = this->get_override("multiple")) { return f(v); } return Base::Multiple(v); } int DefaultMultiple(int v) { return this->Base::Multiple(v); }}; BOOST_PYTHON_MODULE(py_sample) { class_<BaseWrap, boost::noncopyable>("Base") .def("try_multiple", &Base::TryMultiple) .def("try_get_value", &Base::TryGetValue) .def("get_value", pure_virtual(&Base::GetValue)) .def("multiple", &Base::Multiple, &BaseWrap::DefaultMultiple) ; }Copy the code
Make the following call in Python,
from py_sample import Base
class Child(Base):
def multiple(self, v):
return 1000
def get_value(self):
return 1000
child = Child()
base = Base()
print child.try_multiple(1) # 1000
print base.try_multiple() # 0
print child.try_get_value() # 1000
print base.try_get_value() # exception
Copy the code
The try_multiple and try_get_value interfaces defined above are intended to show that by defining them in this way, you can obtain in C++ code the effects of overloading defined in Python.
Function default argument processing
Normal function default argument processing,
int Foo(int a, int b=1) {
return a * b;
}
BOOST_PYTHON_FUNCTION_OVERLOADS(FooOverloads, Foo, 1, 2)
BOOST_PYTHON_MODULE(py_sample) {
def("foo", Foo, FooOverloads());
}
Copy the code
It is wrapped by BOOST_PYTHON_FUNCTION_OVERLOADS, with the 1,2 digits representing the minimum and maximum parameters respectively. Member functions defined on the class are modified with BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS,
class Base { public: int Foo(int a, int b=1) { return a * b; }}; BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(FooOverloads, Base::Foo, 1, 2) BOOST_PYTHON_MODULE(py_sample) { class_<Base>("Base") .def("foo", &Base::Foo, FooOverloads()) ; }Copy the code
Overload processing
Multiple overload functions can be defined in C++. When exporting, for the overload function with a common prefix parameter, BOOST_PYTHON_FUNCTION_OVERLOADS, BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS to help with the export,
class Base { public: int Foo(int a, int b) { return a * b; } int Foo(int a, int b, int c) { return a * b * c; }}; BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(FooOverloads, Base::Foo, 2, 3) BOOST_PYTHON_MODULE(py_sample) { class_<Base>("Base") .def("foo", (int(Base::*)(int, int, int)) 0, FooOverloads()) ; }Copy the code
Export the enumeration
Enumerations are much easier to export,
enum Enum {
FIRST = 0,
SECOND
};
BOOST_PYTHON_MODULE(py_sample) {
enum_<Enum>("Enum")
.value("FIRST", FIRST)
.value("SECOND", SECOND)
;
}
Copy the code
Used in Python,
from py_sample import Enum
print Enum.FIRST, Enum.SECOND
Copy the code
reference
- Boost Python Tutorial
- Boost Python Wiki