mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-21 20:55:11 +00:00
Improve documentation related to inheritance. (#1676)
* Adds section to the reference. * Adds section to advanced classes page describing how to use `get_overload`.
This commit is contained in:
parent
492da592c2
commit
2b045757b5
@ -80,10 +80,10 @@ helper class that is defined as follows:
|
||||
}
|
||||
};
|
||||
|
||||
The macro :func:`PYBIND11_OVERLOAD_PURE` should be used for pure virtual
|
||||
functions, and :func:`PYBIND11_OVERLOAD` should be used for functions which have
|
||||
a default implementation. There are also two alternate macros
|
||||
:func:`PYBIND11_OVERLOAD_PURE_NAME` and :func:`PYBIND11_OVERLOAD_NAME` which
|
||||
The macro :c:macro:`PYBIND11_OVERLOAD_PURE` should be used for pure virtual
|
||||
functions, and :c:macro:`PYBIND11_OVERLOAD` should be used for functions which have
|
||||
a default implementation. There are also two alternate macros
|
||||
:c:macro:`PYBIND11_OVERLOAD_PURE_NAME` and :c:macro:`PYBIND11_OVERLOAD_NAME` which
|
||||
take a string-valued name argument between the *Parent class* and *Name of the
|
||||
function* slots, which defines the name of function in Python. This is required
|
||||
when the C++ and Python versions of the
|
||||
@ -325,6 +325,10 @@ can now create a python class that inherits from ``Dog``:
|
||||
Extended trampoline class functionality
|
||||
=======================================
|
||||
|
||||
.. _extended_class_functionality_forced_trampoline
|
||||
|
||||
Forced trampoline class initialisation
|
||||
--------------------------------------
|
||||
The trampoline classes described in the previous sections are, by default, only
|
||||
initialized when needed. More specifically, they are initialized when a python
|
||||
class actually inherits from a registered type (instead of merely creating an
|
||||
@ -352,6 +356,45 @@ ensuring member initialization and (eventual) destruction.
|
||||
See the file :file:`tests/test_virtual_functions.cpp` for complete examples
|
||||
showing both normal and forced trampoline instantiation.
|
||||
|
||||
Different method signatures
|
||||
---------------------------
|
||||
The macro's introduced in :ref:`overriding_virtuals` cover most of the standard
|
||||
use cases when exposing C++ classes to Python. Sometimes it is hard or unwieldy
|
||||
to create a direct one-on-one mapping between the arguments and method return
|
||||
type.
|
||||
|
||||
An example would be when the C++ signature contains output arguments using
|
||||
references (See also :ref:`faq_reference_arguments`). Another way of solving
|
||||
this is to use the method body of the trampoline class to do conversions to the
|
||||
input and return of the Python method.
|
||||
|
||||
The main building block to do so is the :func:`get_overload`, this function
|
||||
allows retrieving a method implemented in Python from within the trampoline's
|
||||
methods. Consider for example a C++ method which has the signature
|
||||
``bool myMethod(int32_t& value)``, where the return indicates whether
|
||||
something should be done with the ``value``. This can be made convenient on the
|
||||
Python side by allowing the Python function to return ``None`` or an ``int``:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
bool MyClass::myMethod(int32_t& value)
|
||||
{
|
||||
pybind11::gil_scoped_acquire gil; // Acquire the GIL while in this scope.
|
||||
// Try to look up the overloaded method on the Python side.
|
||||
pybind11::function overload = pybind11::get_overload(this, "myMethod");
|
||||
if (overload) { // method is found
|
||||
auto obj = overload(value); // Call the Python function.
|
||||
if (py::isinstance<py::int_>(obj)) { // check if it returned a Python integer type
|
||||
value = obj.cast<int32_t>(); // Cast it and assign it to the value.
|
||||
return true; // Return true; value should be used.
|
||||
} else {
|
||||
return false; // Python returned none, return false.
|
||||
}
|
||||
}
|
||||
return false; // Alternatively return MyClass::myMethod(value);
|
||||
}
|
||||
|
||||
|
||||
.. _custom_constructors:
|
||||
|
||||
Custom constructors
|
||||
|
@ -39,6 +39,8 @@ multiple versions of Python and it finds the wrong one, delete
|
||||
|
||||
cmake -DPYTHON_EXECUTABLE:FILEPATH=<path-to-python-executable> .
|
||||
|
||||
.. _faq_reference_arguments:
|
||||
|
||||
Limitations involving reference arguments
|
||||
=========================================
|
||||
|
||||
|
@ -86,6 +86,21 @@ Python built-in functions
|
||||
.. doxygengroup:: python_builtins
|
||||
:members:
|
||||
|
||||
Inheritance
|
||||
===========
|
||||
|
||||
See :doc:`/classes` and :doc:`/advanced/classes` for more detail.
|
||||
|
||||
.. doxygendefine:: PYBIND11_OVERLOAD
|
||||
|
||||
.. doxygendefine:: PYBIND11_OVERLOAD_PURE
|
||||
|
||||
.. doxygendefine:: PYBIND11_OVERLOAD_NAME
|
||||
|
||||
.. doxygendefine:: PYBIND11_OVERLOAD_PURE_NAME
|
||||
|
||||
.. doxygenfunction:: get_overload
|
||||
|
||||
Exceptions
|
||||
==========
|
||||
|
||||
|
@ -2062,6 +2062,14 @@ inline function get_type_overload(const void *this_ptr, const detail::type_info
|
||||
return overload;
|
||||
}
|
||||
|
||||
/** \rst
|
||||
Try to retrieve a python method by the provided name from the instance pointed to by the this_ptr.
|
||||
|
||||
:this_ptr: The pointer to the object the overload should be retrieved for. This should be the first
|
||||
non-trampoline class encountered in the inheritance chain.
|
||||
:name: The name of the overloaded Python method to retrieve.
|
||||
:return: The Python method by this name from the object or an empty function wrapper.
|
||||
\endrst */
|
||||
template <class T> function get_overload(const T *this_ptr, const char *name) {
|
||||
auto tinfo = detail::get_type_info(typeid(T));
|
||||
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) {
|
||||
} \
|
||||
}
|
||||
|
||||
/** \rst
|
||||
Macro to populate the virtual method in the trampoline class. This macro tries to look up a method named 'fn'
|
||||
from the Python side, deals with the :ref:`gil` and necessary argument conversions to call this method and return
|
||||
the appropriate type. See :ref:`overriding_virtuals` for more information. This macro should be used when the method
|
||||
name in C is not the same as the method name in Python. For example with `__str__`.
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
std::string toString() override {
|
||||
PYBIND11_OVERLOAD_NAME(
|
||||
std::string, // Return type (ret_type)
|
||||
Animal, // Parent class (cname)
|
||||
toString, // Name of function in C++ (name)
|
||||
"__str__", // Name of method in Python (fn)
|
||||
);
|
||||
}
|
||||
\endrst */
|
||||
#define PYBIND11_OVERLOAD_NAME(ret_type, cname, name, fn, ...) \
|
||||
PYBIND11_OVERLOAD_INT(PYBIND11_TYPE(ret_type), PYBIND11_TYPE(cname), name, __VA_ARGS__) \
|
||||
return cname::fn(__VA_ARGS__)
|
||||
|
||||
/** \rst
|
||||
Macro for pure virtual functions, this function is identical to :c:macro:`PYBIND11_OVERLOAD_NAME`, except that it
|
||||
throws if no overload can be found.
|
||||
\endrst */
|
||||
#define PYBIND11_OVERLOAD_PURE_NAME(ret_type, cname, name, fn, ...) \
|
||||
PYBIND11_OVERLOAD_INT(PYBIND11_TYPE(ret_type), PYBIND11_TYPE(cname), name, __VA_ARGS__) \
|
||||
pybind11::pybind11_fail("Tried to call pure virtual function \"" PYBIND11_STRINGIFY(cname) "::" name "\"");
|
||||
|
||||
/** \rst
|
||||
Macro to populate the virtual method in the trampoline class. This macro tries to look up the method
|
||||
from the Python side, deals with the :ref:`gil` and necessary argument conversions to call this method and return
|
||||
the appropriate type. This macro should be used if the method name in C and in Python are identical.
|
||||
See :ref:`overriding_virtuals` for more information.
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
class PyAnimal : public Animal {
|
||||
public:
|
||||
// Inherit the constructors
|
||||
using Animal::Animal;
|
||||
|
||||
// Trampoline (need one for each virtual function)
|
||||
std::string go(int n_times) override {
|
||||
PYBIND11_OVERLOAD_PURE(
|
||||
std::string, // Return type (ret_type)
|
||||
Animal, // Parent class (cname)
|
||||
go, // Name of function in C++ (must match Python name) (fn)
|
||||
n_times // Argument(s) (...)
|
||||
);
|
||||
}
|
||||
};
|
||||
\endrst */
|
||||
#define PYBIND11_OVERLOAD(ret_type, cname, fn, ...) \
|
||||
PYBIND11_OVERLOAD_NAME(PYBIND11_TYPE(ret_type), PYBIND11_TYPE(cname), #fn, fn, __VA_ARGS__)
|
||||
|
||||
/** \rst
|
||||
Macro for pure virtual functions, this function is identical to :c:macro:`PYBIND11_OVERLOAD`, except that it throws
|
||||
if no overload can be found.
|
||||
\endrst */
|
||||
#define PYBIND11_OVERLOAD_PURE(ret_type, cname, fn, ...) \
|
||||
PYBIND11_OVERLOAD_PURE_NAME(PYBIND11_TYPE(ret_type), PYBIND11_TYPE(cname), #fn, fn, __VA_ARGS__)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user