Spaces:
Runtime error
Runtime error
Custom type casters | |
=================== | |
In very rare cases, applications may require custom type casters that cannot be | |
expressed using the abstractions provided by pybind11, thus requiring raw | |
Python C API calls. This is fairly advanced usage and should only be pursued by | |
experts who are familiar with the intricacies of Python reference counting. | |
The following snippets demonstrate how this works for a very simple ``inty`` | |
type that that should be convertible from Python types that provide a | |
``__int__(self)`` method. | |
.. code-block:: cpp | |
struct inty { long long_value; }; | |
void print(inty s) { | |
std::cout << s.long_value << std::endl; | |
} | |
The following Python snippet demonstrates the intended usage from the Python side: | |
.. code-block:: python | |
class A: | |
def __int__(self): | |
return 123 | |
from example import print | |
print(A()) | |
To register the necessary conversion routines, it is necessary to add | |
a partial overload to the ``pybind11::detail::type_caster<T>`` template. | |
Although this is an implementation detail, adding partial overloads to this | |
type is explicitly allowed. | |
.. code-block:: cpp | |
namespace pybind11 { namespace detail { | |
template <> struct type_caster<inty> { | |
public: | |
/** | |
* This macro establishes the name 'inty' in | |
* function signatures and declares a local variable | |
* 'value' of type inty | |
*/ | |
PYBIND11_TYPE_CASTER(inty, _("inty")); | |
/** | |
* Conversion part 1 (Python->C++): convert a PyObject into a inty | |
* instance or return false upon failure. The second argument | |
* indicates whether implicit conversions should be applied. | |
*/ | |
bool load(handle src, bool) { | |
/* Extract PyObject from handle */ | |
PyObject *source = src.ptr(); | |
/* Try converting into a Python integer value */ | |
PyObject *tmp = PyNumber_Long(source); | |
if (!tmp) | |
return false; | |
/* Now try to convert into a C++ int */ | |
value.long_value = PyLong_AsLong(tmp); | |
Py_DECREF(tmp); | |
/* Ensure return code was OK (to avoid out-of-range errors etc) */ | |
return !(value.long_value == -1 && !PyErr_Occurred()); | |
} | |
/** | |
* Conversion part 2 (C++ -> Python): convert an inty instance into | |
* a Python object. The second and third arguments are used to | |
* indicate the return value policy and parent object (for | |
* ``return_value_policy::reference_internal``) and are generally | |
* ignored by implicit casters. | |
*/ | |
static handle cast(inty src, return_value_policy /* policy */, handle /* parent */) { | |
return PyLong_FromLong(src.long_value); | |
} | |
}; | |
}} // namespace pybind11::detail | |
.. note:: | |
A ``type_caster<T>`` defined with ``PYBIND11_TYPE_CASTER(T, ...)`` requires | |
that ``T`` is default-constructible (``value`` is first default constructed | |
and then ``load()`` assigns to it). | |
.. warning:: | |
When using custom type casters, it's important to declare them consistently | |
in every compilation unit of the Python extension module. Otherwise, | |
undefined behavior can ensue. | |