The source code and dockerfile for the GSW2024 AI Lab.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

85 lines
3.1 KiB

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