Wenzel Jakob | 38bd711 | 2015-07-05 20:05:44 +0200 | [diff] [blame] | 1 | # pybind11 -- Seamless operability between C++11 and Python |
| 2 | |
| 3 | **pybind11** is a lightweight header library that exposes C++ types in Python |
| 4 | and vice versa, mainly to create Python bindings of existing C++ code. Its |
| 5 | goals and syntax are similar to the excellent |
| 6 | [Boost.Python](http://www.boost.org/doc/libs/1_58_0/libs/python/doc/) library |
| 7 | by David Abrahams: to minimize boilerplate code in traditional extension |
| 8 | modules by inferring type information using compile-time introspection. |
| 9 | |
| 10 | The main issue with Boost.Python—and the reason for creating such a similar |
| 11 | project—is Boost. Boost is an enormously large and complex suite of utility |
| 12 | libraries that works with almost every C++ compiler in existence. This |
| 13 | compatibility has its cost: arcane template tricks and workarounds are |
| 14 | necessary to support the oldest and buggiest of compiler specimens. Now that |
| 15 | C++11-compatible compilers are widely available, this heavy machinery has |
| 16 | become an excessively large and unnecessary dependency. |
| 17 | |
| 18 | Think of this library as a tiny self-contained version of Boost.Python with |
| 19 | everything stripped away that isn't relevant for binding generation. The whole |
Wenzel Jakob | 2ac80e7 | 2015-07-22 00:59:01 +0200 | [diff] [blame^] | 20 | codebase requires just over 2000 lines of code and just depends on Python and |
Wenzel Jakob | 38bd711 | 2015-07-05 20:05:44 +0200 | [diff] [blame] | 21 | the C++ standard library. This compact implementation was possible thanks to |
| 22 | some of the new C++11 language features (tuples, lambda functions and variadic |
| 23 | templates), and by only targeting Python 3.x and higher. |
| 24 | |
| 25 | ## Core features |
| 26 | The following C++ features can be mapped to Python |
| 27 | |
| 28 | - Functions accepting and returning custom data structures per value, reference, or pointer |
| 29 | - Instance methods and static methods |
| 30 | - Overloaded functions |
| 31 | - Instance attributes and static attributes |
| 32 | - Exceptions |
| 33 | - Enumerations |
| 34 | - Callbacks |
| 35 | - Custom operators |
| 36 | - STL data structures |
| 37 | - Smart pointers with reference counting like `std::shared_ptr` |
| 38 | - Internal references with correct reference counting |
| 39 | |
| 40 | ## Goodies |
| 41 | In addition to the core functionality, pybind11 provides some extra goodies: |
| 42 | |
| 43 | - It's easy to expose the internal storage of custom data types through |
| 44 | Pythons' buffer protocols. This is handy e.g. for fast conversion between |
| 45 | C++ matrix classes like Eigen and NumPy without expensive copy operations. |
| 46 | |
| 47 | - Python's slice-based access and assignment operations can be supported with |
| 48 | just a few lines of code. |
| 49 | |
| 50 | - pybind11 uses C++11 move constructors and move assignment operators whenever |
| 51 | possible to efficiently transfer custom data types. |
| 52 | |
| 53 | ## Limitations |
| 54 | Various things that Boost.Python can do remain unsupported, e.g.: |
| 55 | |
| 56 | - Fine grained exception translation: currently, all exceptions derived from |
| 57 | `std::exception` are mapped to a Python `Exception`, but that's it. |
| 58 | |
| 59 | - Default arguments in C++ functions are ignored, though their effect can be |
| 60 | emulated by binding multiple overloads using anonymous functions. |
| 61 | |
| 62 | - Python keyword arguments are not supported in bindings |
| 63 | |
| 64 | - Weak pointers are not supported |
| 65 | |
| 66 | ## What does the binding code look like? |
| 67 | Here is a simple example. The directory `example` contains many more. |
| 68 | ```C++ |
| 69 | #include <pybind/pybind.h> |
| 70 | #include <pybind/operators.h> |
| 71 | |
| 72 | namespace py = pybind; |
| 73 | |
| 74 | /// Example C++ class which should be bound to Python |
| 75 | class Test { |
| 76 | public: |
| 77 | Test(); |
| 78 | Test(int value); |
| 79 | std::string toString(); |
| 80 | Test operator+(const Test &e) const; |
| 81 | |
| 82 | void print_dict(py::dict dict) { |
| 83 | /* Easily interact with Python types */ |
| 84 | for (auto item : dict) |
| 85 | std::cout << "key=" << item.first << ", " |
| 86 | << "value=" << item.second << std::endl; |
| 87 | } |
| 88 | |
| 89 | int value = 0; |
| 90 | }; |
| 91 | |
| 92 | |
| 93 | PYTHON_PLUGIN(example) { |
| 94 | py::module m("example", "pybind example plugin"); |
| 95 | |
| 96 | py::class_<Test>(m, "Test", "docstring for the Test class") |
| 97 | .def(py::init<>(), "docstring for constructor 1") |
| 98 | .def(py::init<int>(), "docstring for constructor 2") |
| 99 | .def(py::self + py::self, "Addition operator") |
| 100 | .def("__str__", &Test::toString, "Convert to a string representation") |
| 101 | .def("print_dict", &Test::print_dict, "Print a Python dictionary") |
| 102 | .def_readwrite("value", &Test::value, "An instance attribute"); |
| 103 | |
| 104 | return m.ptr(); |
| 105 | } |
| 106 | ``` |