mirror of https://github.com/pybind/pybind11
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
304 lines
8.2 KiB
304 lines
8.2 KiB
.. _classes: |
|
|
|
Object-oriented code |
|
#################### |
|
|
|
Creating bindings for a custom type |
|
=================================== |
|
|
|
Let's now look at a more complex example where we'll create bindings for a |
|
custom C++ data structure named ``Pet``. Its definition is given below: |
|
|
|
.. code-block:: cpp |
|
|
|
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; |
|
}; |
|
|
|
The binding code for ``Pet`` looks as follows: |
|
|
|
.. code-block:: cpp |
|
|
|
#include <pybind/pybind.h> |
|
|
|
namespace py = pybind; |
|
|
|
PYTHON_PLUGIN(example) { |
|
py::module m("example", "pybind example plugin"); |
|
|
|
py::class_<Pet>(m, "Pet") |
|
.def(py::init<const std::string &>()) |
|
.def("setName", &Pet::setName) |
|
.def("getName", &Pet::getName); |
|
|
|
return m.ptr(); |
|
} |
|
|
|
:class:`class_` creates bindings for a C++ `class` or `struct`-style data |
|
structure. :func:`init` is a convenience function that takes the types of a |
|
constructor's parameters as template arguments and wraps the corresponding |
|
constructor (see the :ref:`custom_constructors` section for details). An |
|
interactive Python session demonstrating this example is shown below: |
|
|
|
.. code-block:: python |
|
|
|
% python |
|
>>> import example |
|
>>> p = example.Pet('Molly') |
|
>>> print(p) |
|
<example.Pet object at 0x10cd98060> |
|
>>> p.getName() |
|
u'Molly' |
|
>>> p.setName('Charly') |
|
>>> p.getName() |
|
u'Charly' |
|
|
|
Keyword and default arguments |
|
============================= |
|
It is possible to specify keyword and default arguments using the syntax |
|
discussed in the previous chapter. Refer to the sections :ref:`keyword_args` |
|
and :ref:`default_args` for details. |
|
|
|
Binding lambda functions |
|
======================== |
|
|
|
Note how ``print(p)`` produced a rather useless summary of our data structure in the example above: |
|
|
|
.. code-block:: python |
|
|
|
>>> print(p) |
|
<example.Pet object at 0x10cd98060> |
|
|
|
To address this, we could bind an utility function that returns a human-readable |
|
summary to the special method slot named ``__repr__``. Unfortunately, there is no |
|
suitable functionality in the ``Pet`` data structure, and it would be nice if |
|
we did not have to change it. This can easily be accomplished by binding a |
|
Lambda function instead: |
|
|
|
.. code-block:: cpp |
|
|
|
py::class_<Pet>(m, "Pet") |
|
.def(py::init<const std::string &>()) |
|
.def("setName", &Pet::setName) |
|
.def("getName", &Pet::getName) |
|
.def("__repr__", |
|
[](const Pet &a) { |
|
return "<example.Pet named '" + a.name + "'>"; |
|
} |
|
); |
|
|
|
Both stateless [#f1]_ and stateful lambda closures are supported by pybind11. |
|
With the above change, the same Python code now produces the following output: |
|
|
|
.. code-block:: python |
|
|
|
>>> print(p) |
|
<example.Pet named 'Molly'> |
|
|
|
Instance and static fields |
|
========================== |
|
|
|
We can also directly expose the ``name`` field using the |
|
:func:`class_::def_readwrite` method. A similar :func:`class_::def_readonly` |
|
method also exists for ``const`` fields. |
|
|
|
.. code-block:: cpp |
|
|
|
py::class_<Pet>(m, "Pet") |
|
.def(py::init<const std::string &>()) |
|
.def_readwrite("name", &Pet::name) |
|
// ... remainder ... |
|
|
|
This makes it possible to write |
|
|
|
.. code-block:: python |
|
|
|
>>> p = example.Pet('Molly') |
|
>>> p.name |
|
u'Molly' |
|
>>> p.name = 'Charly' |
|
>>> p.name |
|
u'Charly' |
|
|
|
Now suppose that ``Pet::name`` was a private internal variable |
|
that can only be accessed via setters and getters. |
|
|
|
.. code-block:: cpp |
|
|
|
class Pet { |
|
public: |
|
Pet(const std::string &name) : name(name) { } |
|
void setName(const std::string &name_) { name = name_; } |
|
const std::string &getName() const { return name; } |
|
private: |
|
std::string name; |
|
}; |
|
|
|
In this case, the method :func:`class_::def_property` |
|
(:func:`class_::def_property_readonly` for read-only data) can be used to |
|
provide an interface that is indistinguishable from within Python: |
|
|
|
.. code-block:: cpp |
|
|
|
py::class_<Pet>(m, "Pet") |
|
.def(py::init<const std::string &>()) |
|
.def_property("name", &Pet::getName, &Pet::setName) |
|
// ... remainder ... |
|
|
|
.. seealso:: |
|
|
|
Similar functions :func:`class_::def_readwrite_static`, |
|
:func:`class_::def_readonly_static` :func:`class_::def_property_static`, |
|
and :func:`class_::def_property_readonly_static` are provided for binding |
|
static variables and properties. |
|
|
|
Inheritance |
|
=========== |
|
|
|
Suppose now that the example consists of two data structures with an |
|
inheritance relationship: |
|
|
|
.. code-block:: cpp |
|
|
|
struct Pet { |
|
Pet(const std::string &name) : name(name) { } |
|
std::string name; |
|
}; |
|
|
|
struct Dog : Pet { |
|
Dog(const std::string &name) : Pet(name) { } |
|
std::string bark() const { return "woof!"; } |
|
}; |
|
|
|
To capture the hierarchical relationship in pybind11, we must assign a name to |
|
the ``Pet`` :class:`class_` instance and reference it when binding the ``Dog`` |
|
class. |
|
|
|
.. code-block:: cpp |
|
|
|
py::class_<Pet> pet(m, "Pet"); |
|
pet.def(py::init<const std::string &>()) |
|
.def_readwrite("name", &Pet::name); |
|
|
|
py::class_<Dog>(m, "Dog", pet /* <- specify parent */) |
|
.def(py::init<const std::string &>()) |
|
.def("bark", &Dog::bark); |
|
|
|
Instances then expose fields and methods of both types: |
|
|
|
.. code-block:: python |
|
|
|
>>> p = example.Dog('Molly') |
|
>>> p.name |
|
u'Molly' |
|
>>> p.bark() |
|
u'woof!' |
|
|
|
Overloaded methods |
|
================== |
|
|
|
Sometimes there are several overloaded C++ methods with the same name taking |
|
different kinds of input arguments: |
|
|
|
.. code-block:: cpp |
|
|
|
struct Pet { |
|
Pet(const std::string &name, int age) : name(name), age(age) { } |
|
|
|
void set(int age) { age = age; } |
|
void set(const std::string &name) { name = name; } |
|
|
|
std::string name; |
|
int age; |
|
}; |
|
|
|
Attempting to bind ``Pet::set`` will cause an error since the compiler does not |
|
know which method the user intended to select. We can disambiguate by casting |
|
them to function pointers. Binding multiple functions to the same Python name |
|
automatically creates a chain of fucnction overloads that will be tried in |
|
sequence. |
|
|
|
.. code-block:: cpp |
|
|
|
py::class_<Pet>(m, "Pet") |
|
.def(py::init<const std::string &, int>()) |
|
.def("set", (void (Pet::*)(int)) &Pet::set, "Set the pet's age") |
|
.def("set", (void (Pet::*)(const std::string &)) &Pet::set, "Set the pet's name"); |
|
|
|
The overload signatures are also visible in the method's docstring: |
|
|
|
.. code-block:: python |
|
|
|
>>> help(example.Pet) |
|
|
|
class Pet(__builtin__.object) |
|
| Methods defined here: |
|
| |
|
| __init__(...) |
|
| Signature : (Pet, str, int32_t) -> None |
|
| |
|
| set(...) |
|
| 1. Signature : (Pet, int32_t) -> None |
|
| |
|
| Set the pet's age |
|
| |
|
| 2. Signature : (Pet, str) -> None |
|
| |
|
| Set the pet's name |
|
| |
|
|
|
Enumerations and internal types |
|
=============================== |
|
|
|
Let's now suppose that the example class also contains an internal enumeration |
|
type. |
|
|
|
.. code-block:: cpp |
|
|
|
struct Pet { |
|
enum Kind { |
|
Dog = 0, |
|
Cat |
|
}; |
|
|
|
Pet(const std::string &name, Kind type) : name(name), type(type) { } |
|
|
|
std::string name; |
|
Kind type; |
|
}; |
|
|
|
The binding code for this example looks as follows: |
|
|
|
.. code-block:: cpp |
|
|
|
py::class_<Pet> pet(m, "Pet"); |
|
|
|
pet.def(py::init<const std::string &, Pet::Kind>()) |
|
.def_readwrite("name", &Pet::name) |
|
.def_readwrite("type", &Pet::type); |
|
|
|
py::enum_<Pet::Kind>(pet, "Kind") |
|
.value("Dog", Pet::Kind::Dog) |
|
.value("Cat", Pet::Kind::Cat) |
|
.export_values(); |
|
|
|
To ensure that the ``Kind`` type is created within the scope of ``Pet``, the |
|
``pet`` :class:`class_` instance must be supplied to the :class:`enum_`. |
|
constructor. The :func:`enum_::export_values` function ensures that the enum |
|
entries are exported into the parent scope; skip this call for new C++11-style |
|
strongly typed enums. |
|
|
|
.. code-block:: python |
|
|
|
>>> p = Pet('Lucy', Pet.Cat) |
|
>>> p.type |
|
Kind.Cat |
|
>>> int(p.type) |
|
1L |
|
|
|
|
|
.. [#f1] (those with an empty pair of brackets ``[]`` as the capture object)
|
|
|