pybind11(available in https://github.com/pybind/pybind11) is a lightweight header-only library that exposes C++ types in Python and vice versa, mainly to create Python bindings of existing C++ code
similar project: Boost.python
advantages of pybind compared to Boost.python:
dramatically simpler binding code in many common situations
Include with PyPI
pip install pybind11
- Functions accepting and returning custom data structures per value, reference, or pointer
// example.cpp #includeint add(int i, int j) { return i + j; } PYBIND11_MODULE(example, m) { m.doc() = "pybind11 example plugin"; // optional module docstring m.def("add", &add, "A function which adds two numbers"); }
# CMakeLists
find_package(pybind11)
pybind11_add_module(example
example.cpp
)
m.doc()–>对于这一个module的说明
PYBIND11_MODULE(example, m)中example是module的名字,m defines a variable of type
py::module_ which can be used to initialize the module.
- Object-oriented code
struct Pet {
Pet(const std::string &name) : name(name) { }
void setName(const std::string &name_) { name = name_; }
const std::string &getName() const { return name; }
std::string name;
};
#includenamespace py = pybind11; PYBIND11_MODULE(example, m) { py::class_ (m, "Pet") .def(py::init ()) .def("setName", &Pet::setName) .def("getName", &Pet::getName); }
% python
>>> import example
>>> p = example.Pet('Molly')
>>> print(p)
>>> p.getName()
u'Molly'
>>> p.setName('Charly')
>>> p.getName()
u'Charly'
注意到上面的print打印出的内容对于我们掌握pet的信息并没有什么帮助,所以我们可以重写,增加一句
.def("__repr__",
[](const Pet &a) {
return "";
}
此时
print(p)
还能在python端给类增加新的属性
py::class_(m, "Pet", py::dynamic_attr()) .def(py::init<>()) .def_readwrite("name", &Pet::name);
p = example.Pet()
>>> p.name = 'Charly' # OK, overwrite value in C++
>>> p.age = 2 # OK, dynamically add a new attribute
>>> p.__dict__ # just like a native Python class
{'age': 2}
方法重载
py::class_(m, "Pet") .def("set", py::overload_cast (&Pet::set), "Set the pet's age") .def("set", py::overload_cast (&Pet::set), "Set the pet's name");
- Functions
return value policies(具体说明在官方文档),默认的为automatic
a wrong example
Data *get_data() { return _data; }
...
m.def("get_data", &get_data); // <-- KABOOM, will cause crash when called from Python
需要被更改为
m.def("get_data", &get_data, py::return_value_policy::reference);
- Class
如果在类中定义了纯虚函数,那么在绑定的时候需要定义一个trampoline class来辅助绑定
范例:
class Animal {
public:
virtual ~Animal() { }
virtual std::string go(int n_times) = 0;
};
class Dog : public Animal {
public:
std::string go(int n_times) override {
std::string result;
for (int i=0; i
trampoline class:
class PyAnimal : public Animal {
public:
using Animal::Animal;
std::string go(int n_times) override {
PYBIND11_OVERRIDE_PURE(
std::string,
Animal,
go,
n_times
);
}
};
绑定代码:
PYBIND11_MODULE(example, m) {
py::class_(m, "Animal")
.def(py::init<>())
.def("go", &Animal::go);
py::class_(m, "Dog")
.def(py::init<>());
m.def("call_go", &call_go);
}
py_heuristic_load_planner中
class ContainerTrampoline
: public Container
{
public:
using base_container_t = Container;
using base_container_t::base_container_t;
void load_all() override
{
PYBIND11_OVERRIDE(void, base_container_t, load_all,
);
}
LoadStatus load_once() override
{
PYBIND11_OVERRIDE_PURE(LoadStatus, base_container_t, load_once,
);
}
};
注意在PYBIND11_OVERRIDE中是只识别逗号的,所以当使用带有多个模板的模板类的时候需要先使用using关键字,再填写否则会报错
pybind11还能够绑定factory function和lamda function
pickling support:
Python’s pickle module provides a powerful facility to serialize and de-serialize a Python object graph into a binary data stream
class Pickleable {
public:
Pickleable(const std::string &value) : m_value(value) { }
const std::string &value() const { return m_value; }
void setExtra(int extra) { m_extra = extra; }
int extra() const { return m_extra; }
private:
std::string m_value;
int m_extra = 0;
};
py::class_(m, "Pickleable")
.def(py::init())
.def("value", &Pickleable::value)
.def("extra", &Pickleable::extra)
.def("setExtra", &Pickleable::setExtra)
.def(py::pickle(
[](const Pickleable &p) { // __getstate__
return py::make_tuple(p.value(), p.extra());
},
[](py::tuple t) { // __setstate__
if (t.size() != 2)
throw std::runtime_error("Invalid state!");
Pickleable p(t[0].cast());
p.setExtra(t[1].cast());
return p;
}
));
- Smart pointers
std::unique_ptr:
不用做额外处理
std::shared_ptr:
#include
namespace py = pybind11;
class Child { };
class Parent {
public:
Parent() : child(std::make_shared()) { }
private:
std::shared_ptr child;
};
PYBIND11_MODULE(example, m) {
py::class_>(m, "Child");
py::class_>(m, "Parent")
.def(py::init<>());
}
Reference: https://pybind11.readthedocs.io/en/latest/



