111986Sandreas.sandberg@arm.comCustom type casters
211986Sandreas.sandberg@arm.com===================
311986Sandreas.sandberg@arm.com
411986Sandreas.sandberg@arm.comIn very rare cases, applications may require custom type casters that cannot be
511986Sandreas.sandberg@arm.comexpressed using the abstractions provided by pybind11, thus requiring raw
611986Sandreas.sandberg@arm.comPython C API calls. This is fairly advanced usage and should only be pursued by
711986Sandreas.sandberg@arm.comexperts who are familiar with the intricacies of Python reference counting.
811986Sandreas.sandberg@arm.com
911986Sandreas.sandberg@arm.comThe following snippets demonstrate how this works for a very simple ``inty``
1011986Sandreas.sandberg@arm.comtype that that should be convertible from Python types that provide a
1111986Sandreas.sandberg@arm.com``__int__(self)`` method.
1211986Sandreas.sandberg@arm.com
1311986Sandreas.sandberg@arm.com.. code-block:: cpp
1411986Sandreas.sandberg@arm.com
1511986Sandreas.sandberg@arm.com    struct inty { long long_value; };
1611986Sandreas.sandberg@arm.com
1711986Sandreas.sandberg@arm.com    void print(inty s) {
1811986Sandreas.sandberg@arm.com        std::cout << s.long_value << std::endl;
1911986Sandreas.sandberg@arm.com    }
2011986Sandreas.sandberg@arm.com
2111986Sandreas.sandberg@arm.comThe following Python snippet demonstrates the intended usage from the Python side:
2211986Sandreas.sandberg@arm.com
2311986Sandreas.sandberg@arm.com.. code-block:: python
2411986Sandreas.sandberg@arm.com
2511986Sandreas.sandberg@arm.com    class A:
2611986Sandreas.sandberg@arm.com        def __int__(self):
2711986Sandreas.sandberg@arm.com            return 123
2811986Sandreas.sandberg@arm.com
2911986Sandreas.sandberg@arm.com    from example import print
3011986Sandreas.sandberg@arm.com    print(A())
3111986Sandreas.sandberg@arm.com
3211986Sandreas.sandberg@arm.comTo register the necessary conversion routines, it is necessary to add
3311986Sandreas.sandberg@arm.coma partial overload to the ``pybind11::detail::type_caster<T>`` template.
3411986Sandreas.sandberg@arm.comAlthough this is an implementation detail, adding partial overloads to this
3511986Sandreas.sandberg@arm.comtype is explicitly allowed.
3611986Sandreas.sandberg@arm.com
3711986Sandreas.sandberg@arm.com.. code-block:: cpp
3811986Sandreas.sandberg@arm.com
3911986Sandreas.sandberg@arm.com    namespace pybind11 { namespace detail {
4011986Sandreas.sandberg@arm.com        template <> struct type_caster<inty> {
4111986Sandreas.sandberg@arm.com        public:
4211986Sandreas.sandberg@arm.com            /**
4311986Sandreas.sandberg@arm.com             * This macro establishes the name 'inty' in
4411986Sandreas.sandberg@arm.com             * function signatures and declares a local variable
4511986Sandreas.sandberg@arm.com             * 'value' of type inty
4611986Sandreas.sandberg@arm.com             */
4711986Sandreas.sandberg@arm.com            PYBIND11_TYPE_CASTER(inty, _("inty"));
4811986Sandreas.sandberg@arm.com
4911986Sandreas.sandberg@arm.com            /**
5011986Sandreas.sandberg@arm.com             * Conversion part 1 (Python->C++): convert a PyObject into a inty
5111986Sandreas.sandberg@arm.com             * instance or return false upon failure. The second argument
5211986Sandreas.sandberg@arm.com             * indicates whether implicit conversions should be applied.
5311986Sandreas.sandberg@arm.com             */
5411986Sandreas.sandberg@arm.com            bool load(handle src, bool) {
5511986Sandreas.sandberg@arm.com                /* Extract PyObject from handle */
5611986Sandreas.sandberg@arm.com                PyObject *source = src.ptr();
5711986Sandreas.sandberg@arm.com                /* Try converting into a Python integer value */
5811986Sandreas.sandberg@arm.com                PyObject *tmp = PyNumber_Long(source);
5911986Sandreas.sandberg@arm.com                if (!tmp)
6011986Sandreas.sandberg@arm.com                    return false;
6111986Sandreas.sandberg@arm.com                /* Now try to convert into a C++ int */
6211986Sandreas.sandberg@arm.com                value.long_value = PyLong_AsLong(tmp);
6311986Sandreas.sandberg@arm.com                Py_DECREF(tmp);
6411986Sandreas.sandberg@arm.com                /* Ensure return code was OK (to avoid out-of-range errors etc) */
6511986Sandreas.sandberg@arm.com                return !(value.long_value == -1 && !PyErr_Occurred());
6611986Sandreas.sandberg@arm.com            }
6711986Sandreas.sandberg@arm.com
6811986Sandreas.sandberg@arm.com            /**
6911986Sandreas.sandberg@arm.com             * Conversion part 2 (C++ -> Python): convert an inty instance into
7011986Sandreas.sandberg@arm.com             * a Python object. The second and third arguments are used to
7111986Sandreas.sandberg@arm.com             * indicate the return value policy and parent object (for
7211986Sandreas.sandberg@arm.com             * ``return_value_policy::reference_internal``) and are generally
7311986Sandreas.sandberg@arm.com             * ignored by implicit casters.
7411986Sandreas.sandberg@arm.com             */
7511986Sandreas.sandberg@arm.com            static handle cast(inty src, return_value_policy /* policy */, handle /* parent */) {
7611986Sandreas.sandberg@arm.com                return PyLong_FromLong(src.long_value);
7711986Sandreas.sandberg@arm.com            }
7811986Sandreas.sandberg@arm.com        };
7911986Sandreas.sandberg@arm.com    }} // namespace pybind11::detail
8011986Sandreas.sandberg@arm.com
8112391Sjason@lowepower.com.. note::
8212391Sjason@lowepower.com
8312391Sjason@lowepower.com    A ``type_caster<T>`` defined with ``PYBIND11_TYPE_CASTER(T, ...)`` requires
8412391Sjason@lowepower.com    that ``T`` is default-constructible (``value`` is first default constructed
8512391Sjason@lowepower.com    and then ``load()`` assigns to it).
8612391Sjason@lowepower.com
8711986Sandreas.sandberg@arm.com.. warning::
8811986Sandreas.sandberg@arm.com
8911986Sandreas.sandberg@arm.com    When using custom type casters, it's important to declare them consistently
9011986Sandreas.sandberg@arm.com    in every compilation unit of the Python extension module. Otherwise,
9111986Sandreas.sandberg@arm.com    undefined behavior can ensue.
92