86 lines
3.1 KiB
ReStructuredText
86 lines
3.1 KiB
ReStructuredText
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
|
|
|
|
.. 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.
|