mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-25 14:45:12 +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
|
The macro :c:macro:`PYBIND11_OVERLOAD_PURE` should be used for pure virtual
|
||||||
functions, and :func:`PYBIND11_OVERLOAD` should be used for functions which have
|
functions, and :c:macro:`PYBIND11_OVERLOAD` should be used for functions which have
|
||||||
a default implementation. There are also two alternate macros
|
a default implementation. There are also two alternate macros
|
||||||
:func:`PYBIND11_OVERLOAD_PURE_NAME` and :func:`PYBIND11_OVERLOAD_NAME` which
|
: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
|
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
|
function* slots, which defines the name of function in Python. This is required
|
||||||
when the C++ and Python versions of the
|
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 trampoline class functionality
|
||||||
=======================================
|
=======================================
|
||||||
|
|
||||||
|
.. _extended_class_functionality_forced_trampoline
|
||||||
|
|
||||||
|
Forced trampoline class initialisation
|
||||||
|
--------------------------------------
|
||||||
The trampoline classes described in the previous sections are, by default, only
|
The trampoline classes described in the previous sections are, by default, only
|
||||||
initialized when needed. More specifically, they are initialized when a python
|
initialized when needed. More specifically, they are initialized when a python
|
||||||
class actually inherits from a registered type (instead of merely creating an
|
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
|
See the file :file:`tests/test_virtual_functions.cpp` for complete examples
|
||||||
showing both normal and forced trampoline instantiation.
|
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:
|
||||||
|
|
||||||
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> .
|
cmake -DPYTHON_EXECUTABLE:FILEPATH=<path-to-python-executable> .
|
||||||
|
|
||||||
|
.. _faq_reference_arguments:
|
||||||
|
|
||||||
Limitations involving reference arguments
|
Limitations involving reference arguments
|
||||||
=========================================
|
=========================================
|
||||||
|
|
||||||
|
@ -86,6 +86,21 @@ Python built-in functions
|
|||||||
.. doxygengroup:: python_builtins
|
.. doxygengroup:: python_builtins
|
||||||
:members:
|
: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
|
Exceptions
|
||||||
==========
|
==========
|
||||||
|
|
||||||
|
@ -2062,6 +2062,14 @@ inline function get_type_overload(const void *this_ptr, const detail::type_info
|
|||||||
return overload;
|
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) {
|
template <class T> function get_overload(const T *this_ptr, const char *name) {
|
||||||
auto tinfo = detail::get_type_info(typeid(T));
|
auto tinfo = detail::get_type_info(typeid(T));
|
||||||
return tinfo ? get_type_overload(this_ptr, tinfo, name) : function();
|
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, ...) \
|
#define PYBIND11_OVERLOAD_NAME(ret_type, cname, name, fn, ...) \
|
||||||
PYBIND11_OVERLOAD_INT(PYBIND11_TYPE(ret_type), PYBIND11_TYPE(cname), name, __VA_ARGS__) \
|
PYBIND11_OVERLOAD_INT(PYBIND11_TYPE(ret_type), PYBIND11_TYPE(cname), name, __VA_ARGS__) \
|
||||||
return cname::fn(__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, ...) \
|
#define PYBIND11_OVERLOAD_PURE_NAME(ret_type, cname, name, fn, ...) \
|
||||||
PYBIND11_OVERLOAD_INT(PYBIND11_TYPE(ret_type), PYBIND11_TYPE(cname), name, __VA_ARGS__) \
|
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 "\"");
|
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, ...) \
|
#define PYBIND11_OVERLOAD(ret_type, cname, fn, ...) \
|
||||||
PYBIND11_OVERLOAD_NAME(PYBIND11_TYPE(ret_type), PYBIND11_TYPE(cname), #fn, fn, __VA_ARGS__)
|
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, ...) \
|
#define PYBIND11_OVERLOAD_PURE(ret_type, cname, fn, ...) \
|
||||||
PYBIND11_OVERLOAD_PURE_NAME(PYBIND11_TYPE(ret_type), PYBIND11_TYPE(cname), #fn, fn, __VA_ARGS__)
|
PYBIND11_OVERLOAD_PURE_NAME(PYBIND11_TYPE(ret_type), PYBIND11_TYPE(cname), #fn, fn, __VA_ARGS__)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user