Dean Moldovan | 67b52d8 | 2016-10-16 19:12:43 +0200 | [diff] [blame^] | 1 | Custom type casters |
| 2 | =================== |
| 3 | |
| 4 | In very rare cases, applications may require custom type casters that cannot be |
| 5 | expressed using the abstractions provided by pybind11, thus requiring raw |
| 6 | Python C API calls. This is fairly advanced usage and should only be pursued by |
| 7 | experts who are familiar with the intricacies of Python reference counting. |
| 8 | |
| 9 | The following snippets demonstrate how this works for a very simple ``inty`` |
| 10 | type that that should be convertible from Python types that provide a |
| 11 | ``__int__(self)`` method. |
| 12 | |
| 13 | .. code-block:: cpp |
| 14 | |
| 15 | struct inty { long long_value; }; |
| 16 | |
| 17 | void print(inty s) { |
| 18 | std::cout << s.long_value << std::endl; |
| 19 | } |
| 20 | |
| 21 | The following Python snippet demonstrates the intended usage from the Python side: |
| 22 | |
| 23 | .. code-block:: python |
| 24 | |
| 25 | class A: |
| 26 | def __int__(self): |
| 27 | return 123 |
| 28 | |
| 29 | from example import print |
| 30 | print(A()) |
| 31 | |
| 32 | To register the necessary conversion routines, it is necessary to add |
| 33 | a partial overload to the ``pybind11::detail::type_caster<T>`` template. |
| 34 | Although this is an implementation detail, adding partial overloads to this |
| 35 | type is explicitly allowed. |
| 36 | |
| 37 | .. code-block:: cpp |
| 38 | |
| 39 | namespace pybind11 { namespace detail { |
| 40 | template <> struct type_caster<inty> { |
| 41 | public: |
| 42 | /** |
| 43 | * This macro establishes the name 'inty' in |
| 44 | * function signatures and declares a local variable |
| 45 | * 'value' of type inty |
| 46 | */ |
| 47 | PYBIND11_TYPE_CASTER(inty, _("inty")); |
| 48 | |
| 49 | /** |
| 50 | * Conversion part 1 (Python->C++): convert a PyObject into a inty |
| 51 | * instance or return false upon failure. The second argument |
| 52 | * indicates whether implicit conversions should be applied. |
| 53 | */ |
| 54 | bool load(handle src, bool) { |
| 55 | /* Extract PyObject from handle */ |
| 56 | PyObject *source = src.ptr(); |
| 57 | /* Try converting into a Python integer value */ |
| 58 | PyObject *tmp = PyNumber_Long(source); |
| 59 | if (!tmp) |
| 60 | return false; |
| 61 | /* Now try to convert into a C++ int */ |
| 62 | value.long_value = PyLong_AsLong(tmp); |
| 63 | Py_DECREF(tmp); |
| 64 | /* Ensure return code was OK (to avoid out-of-range errors etc) */ |
| 65 | return !(value.long_value == -1 && !PyErr_Occurred()); |
| 66 | } |
| 67 | |
| 68 | /** |
| 69 | * Conversion part 2 (C++ -> Python): convert an inty instance into |
| 70 | * a Python object. The second and third arguments are used to |
| 71 | * indicate the return value policy and parent object (for |
| 72 | * ``return_value_policy::reference_internal``) and are generally |
| 73 | * ignored by implicit casters. |
| 74 | */ |
| 75 | static handle cast(inty src, return_value_policy /* policy */, handle /* parent */) { |
| 76 | return PyLong_FromLong(src.long_value); |
| 77 | } |
| 78 | }; |
| 79 | }} // namespace pybind11::detail |