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