Skip to content

Commit 2b04575

Browse files
iwanderswjakob
authored andcommitted
Improve documentation related to inheritance. (pybind#1676)
* Adds section to the reference. * Adds section to advanced classes page describing how to use `get_overload`.
1 parent 492da59 commit 2b04575

File tree

4 files changed

+121
-4
lines changed

4 files changed

+121
-4
lines changed

docs/advanced/classes.rst

+47-4
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,10 @@ helper class that is defined as follows:
8080
}
8181
};
8282
83-
The macro :func:`PYBIND11_OVERLOAD_PURE` should be used for pure virtual
84-
functions, and :func:`PYBIND11_OVERLOAD` should be used for functions which have
85-
a default implementation. There are also two alternate macros
86-
:func:`PYBIND11_OVERLOAD_PURE_NAME` and :func:`PYBIND11_OVERLOAD_NAME` which
83+
The macro :c:macro:`PYBIND11_OVERLOAD_PURE` should be used for pure virtual
84+
functions, and :c:macro:`PYBIND11_OVERLOAD` should be used for functions which have
85+
a default implementation. There are also two alternate macros
86+
:c:macro:`PYBIND11_OVERLOAD_PURE_NAME` and :c:macro:`PYBIND11_OVERLOAD_NAME` which
8787
take a string-valued name argument between the *Parent class* and *Name of the
8888
function* slots, which defines the name of function in Python. This is required
8989
when the C++ and Python versions of the
@@ -325,6 +325,10 @@ can now create a python class that inherits from ``Dog``:
325325
Extended trampoline class functionality
326326
=======================================
327327

328+
.. _extended_class_functionality_forced_trampoline
329+
330+
Forced trampoline class initialisation
331+
--------------------------------------
328332
The trampoline classes described in the previous sections are, by default, only
329333
initialized when needed. More specifically, they are initialized when a python
330334
class actually inherits from a registered type (instead of merely creating an
@@ -352,6 +356,45 @@ ensuring member initialization and (eventual) destruction.
352356
See the file :file:`tests/test_virtual_functions.cpp` for complete examples
353357
showing both normal and forced trampoline instantiation.
354358

359+
Different method signatures
360+
---------------------------
361+
The macro's introduced in :ref:`overriding_virtuals` cover most of the standard
362+
use cases when exposing C++ classes to Python. Sometimes it is hard or unwieldy
363+
to create a direct one-on-one mapping between the arguments and method return
364+
type.
365+
366+
An example would be when the C++ signature contains output arguments using
367+
references (See also :ref:`faq_reference_arguments`). Another way of solving
368+
this is to use the method body of the trampoline class to do conversions to the
369+
input and return of the Python method.
370+
371+
The main building block to do so is the :func:`get_overload`, this function
372+
allows retrieving a method implemented in Python from within the trampoline's
373+
methods. Consider for example a C++ method which has the signature
374+
``bool myMethod(int32_t& value)``, where the return indicates whether
375+
something should be done with the ``value``. This can be made convenient on the
376+
Python side by allowing the Python function to return ``None`` or an ``int``:
377+
378+
.. code-block:: cpp
379+
380+
bool MyClass::myMethod(int32_t& value)
381+
{
382+
pybind11::gil_scoped_acquire gil; // Acquire the GIL while in this scope.
383+
// Try to look up the overloaded method on the Python side.
384+
pybind11::function overload = pybind11::get_overload(this, "myMethod");
385+
if (overload) { // method is found
386+
auto obj = overload(value); // Call the Python function.
387+
if (py::isinstance<py::int_>(obj)) { // check if it returned a Python integer type
388+
value = obj.cast<int32_t>(); // Cast it and assign it to the value.
389+
return true; // Return true; value should be used.
390+
} else {
391+
return false; // Python returned none, return false.
392+
}
393+
}
394+
return false; // Alternatively return MyClass::myMethod(value);
395+
}
396+
397+
355398
.. _custom_constructors:
356399

357400
Custom constructors

docs/faq.rst

+2
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ multiple versions of Python and it finds the wrong one, delete
3939
4040
cmake -DPYTHON_EXECUTABLE:FILEPATH=<path-to-python-executable> .
4141
42+
.. _faq_reference_arguments:
43+
4244
Limitations involving reference arguments
4345
=========================================
4446

docs/reference.rst

+15
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,21 @@ Python built-in functions
8686
.. doxygengroup:: python_builtins
8787
:members:
8888

89+
Inheritance
90+
===========
91+
92+
See :doc:`/classes` and :doc:`/advanced/classes` for more detail.
93+
94+
.. doxygendefine:: PYBIND11_OVERLOAD
95+
96+
.. doxygendefine:: PYBIND11_OVERLOAD_PURE
97+
98+
.. doxygendefine:: PYBIND11_OVERLOAD_NAME
99+
100+
.. doxygendefine:: PYBIND11_OVERLOAD_PURE_NAME
101+
102+
.. doxygenfunction:: get_overload
103+
89104
Exceptions
90105
==========
91106

include/pybind11/pybind11.h

+57
Original file line numberDiff line numberDiff line change
@@ -2062,6 +2062,14 @@ inline function get_type_overload(const void *this_ptr, const detail::type_info
20622062
return overload;
20632063
}
20642064

2065+
/** \rst
2066+
Try to retrieve a python method by the provided name from the instance pointed to by the this_ptr.
2067+
2068+
:this_ptr: The pointer to the object the overload should be retrieved for. This should be the first
2069+
non-trampoline class encountered in the inheritance chain.
2070+
:name: The name of the overloaded Python method to retrieve.
2071+
:return: The Python method by this name from the object or an empty function wrapper.
2072+
\endrst */
20652073
template <class T> function get_overload(const T *this_ptr, const char *name) {
20662074
auto tinfo = detail::get_type_info(typeid(T));
20672075
return tinfo ? get_type_overload(this_ptr, tinfo, name) : function();
@@ -2080,17 +2088,66 @@ template <class T> function get_overload(const T *this_ptr, const char *name) {
20802088
} \
20812089
}
20822090

2091+
/** \rst
2092+
Macro to populate the virtual method in the trampoline class. This macro tries to look up a method named 'fn'
2093+
from the Python side, deals with the :ref:`gil` and necessary argument conversions to call this method and return
2094+
the appropriate type. See :ref:`overriding_virtuals` for more information. This macro should be used when the method
2095+
name in C is not the same as the method name in Python. For example with `__str__`.
2096+
2097+
.. code-block:: cpp
2098+
2099+
std::string toString() override {
2100+
PYBIND11_OVERLOAD_NAME(
2101+
std::string, // Return type (ret_type)
2102+
Animal, // Parent class (cname)
2103+
toString, // Name of function in C++ (name)
2104+
"__str__", // Name of method in Python (fn)
2105+
);
2106+
}
2107+
\endrst */
20832108
#define PYBIND11_OVERLOAD_NAME(ret_type, cname, name, fn, ...) \
20842109
PYBIND11_OVERLOAD_INT(PYBIND11_TYPE(ret_type), PYBIND11_TYPE(cname), name, __VA_ARGS__) \
20852110
return cname::fn(__VA_ARGS__)
20862111

2112+
/** \rst
2113+
Macro for pure virtual functions, this function is identical to :c:macro:`PYBIND11_OVERLOAD_NAME`, except that it
2114+
throws if no overload can be found.
2115+
\endrst */
20872116
#define PYBIND11_OVERLOAD_PURE_NAME(ret_type, cname, name, fn, ...) \
20882117
PYBIND11_OVERLOAD_INT(PYBIND11_TYPE(ret_type), PYBIND11_TYPE(cname), name, __VA_ARGS__) \
20892118
pybind11::pybind11_fail("Tried to call pure virtual function \"" PYBIND11_STRINGIFY(cname) "::" name "\"");
20902119

2120+
/** \rst
2121+
Macro to populate the virtual method in the trampoline class. This macro tries to look up the method
2122+
from the Python side, deals with the :ref:`gil` and necessary argument conversions to call this method and return
2123+
the appropriate type. This macro should be used if the method name in C and in Python are identical.
2124+
See :ref:`overriding_virtuals` for more information.
2125+
2126+
.. code-block:: cpp
2127+
2128+
class PyAnimal : public Animal {
2129+
public:
2130+
// Inherit the constructors
2131+
using Animal::Animal;
2132+
2133+
// Trampoline (need one for each virtual function)
2134+
std::string go(int n_times) override {
2135+
PYBIND11_OVERLOAD_PURE(
2136+
std::string, // Return type (ret_type)
2137+
Animal, // Parent class (cname)
2138+
go, // Name of function in C++ (must match Python name) (fn)
2139+
n_times // Argument(s) (...)
2140+
);
2141+
}
2142+
};
2143+
\endrst */
20912144
#define PYBIND11_OVERLOAD(ret_type, cname, fn, ...) \
20922145
PYBIND11_OVERLOAD_NAME(PYBIND11_TYPE(ret_type), PYBIND11_TYPE(cname), #fn, fn, __VA_ARGS__)
20932146

2147+
/** \rst
2148+
Macro for pure virtual functions, this function is identical to :c:macro:`PYBIND11_OVERLOAD`, except that it throws
2149+
if no overload can be found.
2150+
\endrst */
20942151
#define PYBIND11_OVERLOAD_PURE(ret_type, cname, fn, ...) \
20952152
PYBIND11_OVERLOAD_PURE_NAME(PYBIND11_TYPE(ret_type), PYBIND11_TYPE(cname), #fn, fn, __VA_ARGS__)
20962153

0 commit comments

Comments
 (0)