Hide navigation sidebar
Hide table of contents sidebar
Skip to content
Back to top
View this page
Toggle table of contents sidebar

# 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.

    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:

    class A:
        def __int__(self):
            return 123

    from example import print

    print(A())

To register the necessary conversion routines, it is necessary to add an instantiation of the `pybind11::detail::type_caster<T>` template. Although this is an implementation detail, adding an instantiation of this type is explicitly allowed.

    namespace PYBIND11_NAMESPACE { 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, const_name("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_NAMESPACE::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.