test_custom_type_casters.cpp
Go to the documentation of this file.
1 /*
2  tests/test_custom_type_casters.cpp -- tests type_caster<T>
3 
4  Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
5 
6  All rights reserved. Use of this source code is governed by a
7  BSD-style license that can be found in the LICENSE file.
8 */
9 
10 #include "constructor_stats.h"
11 #include "pybind11_tests.h"
12 
13 // py::arg/py::arg_v testing: these arguments just record their argument when invoked
15 public:
16  std::string arg = "(default arg inspector 1)";
17 };
19 public:
20  std::string arg = "(default arg inspector 2)";
21 };
23 
24 namespace pybind11 {
25 namespace detail {
26 template <>
28 public:
29  // Classic
30 #ifdef PYBIND11_DETAIL_UNDERSCORE_BACKWARD_COMPATIBILITY
31  PYBIND11_TYPE_CASTER(ArgInspector1, _("ArgInspector1"));
32 #else
34 #endif
35 
36  bool load(handle src, bool convert) {
37  value.arg = "loading ArgInspector1 argument " + std::string(convert ? "WITH" : "WITHOUT")
38  + " conversion allowed. "
39  "Argument value = "
40  + (std::string) str(src);
41  return true;
42  }
43 
45  return str(src.arg).release();
46  }
47 };
48 template <>
50 public:
52 
53  bool load(handle src, bool convert) {
54  value.arg = "loading ArgInspector2 argument " + std::string(convert ? "WITH" : "WITHOUT")
55  + " conversion allowed. "
56  "Argument value = "
57  + (std::string) str(src);
58  return true;
59  }
60 
62  return str(src.arg).release();
63  }
64 };
65 template <>
67 public:
68  PYBIND11_TYPE_CASTER(ArgAlwaysConverts, const_name("ArgAlwaysConverts"));
69 
70  bool load(handle, bool convert) { return convert; }
71 
73  return py::none().release();
74  }
75 };
76 } // namespace detail
77 } // namespace pybind11
78 
79 // test_custom_caster_destruction
81 public:
87  print_copy_assigned(this);
88  return *this;
89  }
91  print_move_assigned(this);
92  return *this;
93  }
94 };
95 namespace pybind11 {
96 namespace detail {
97 template <>
99  PYBIND11_TYPE_CASTER(DestructionTester, const_name("DestructionTester"));
100  bool load(handle, bool) { return true; }
101 
103  return py::bool_(true).release();
104  }
105 };
106 } // namespace detail
107 } // namespace pybind11
108 
109 // Define type caster outside of `pybind11::detail` and then alias it.
110 namespace other_lib {
111 struct MyType {};
112 // Corrupt `py` shorthand alias for surrounding context.
113 namespace py {}
114 // Corrupt unqualified relative `pybind11` namespace.
115 namespace pybind11 {}
116 // Correct alias.
117 namespace py_ = ::pybind11;
118 // Define caster. This is effectively no-op, we only ensure it compiles and we
119 // don't have any symbol collision when using macro mixin.
120 struct my_caster {
122  bool load(py_::handle, bool) { return true; }
123 
124  static py_::handle cast(const MyType &, py_::return_value_policy, py_::handle) {
125  return py_::bool_(true).release();
126  }
127 };
128 } // namespace other_lib
129 // Effectively "alias" it into correct namespace (via inheritance).
130 namespace pybind11 {
131 namespace detail {
132 template <>
134 } // namespace detail
135 } // namespace pybind11
136 
137 TEST_SUBMODULE(custom_type_casters, m) {
138  // test_custom_type_casters
139 
140  // test_noconvert_args
141  //
142  // Test converting. The ArgAlwaysConverts is just there to make the first no-conversion pass
143  // fail so that our call always ends up happening via the second dispatch (the one that allows
144  // some conversion).
145  class ArgInspector {
146  public:
148  std::string g(const ArgInspector1 &a,
149  const ArgInspector1 &b,
150  int c,
151  ArgInspector2 *d,
153  return a.arg + "\n" + b.arg + "\n" + std::to_string(c) + "\n" + d->arg;
154  }
155  static ArgInspector2 h(ArgInspector2 a, ArgAlwaysConverts) { return a; }
156  };
157  // [workaround(intel)] ICC 20/21 breaks with py::arg().stuff, using py::arg{}.stuff works.
158  py::class_<ArgInspector>(m, "ArgInspector")
159  .def(py::init<>())
160  .def("f", &ArgInspector::f, py::arg(), py::arg() = ArgAlwaysConverts())
161  .def("g",
163  "a"_a.noconvert(),
164  "b"_a,
165  "c"_a.noconvert() = 13,
166  "d"_a = ArgInspector2(),
168  .def_static("h", &ArgInspector::h, py::arg{}.noconvert(), py::arg() = ArgAlwaysConverts());
169  m.def(
170  "arg_inspect_func",
171  [](const ArgInspector2 &a, const ArgInspector1 &b, ArgAlwaysConverts) {
172  return a.arg + "\n" + b.arg;
173  },
174  py::arg{}.noconvert(false),
175  py::arg_v(nullptr, ArgInspector1()).noconvert(true),
176  py::arg() = ArgAlwaysConverts());
177 
178  m.def(
179  "floats_preferred", [](double f) { return 0.5 * f; }, "f"_a);
180  m.def(
181  "floats_only", [](double f) { return 0.5 * f; }, "f"_a.noconvert());
182  m.def(
183  "ints_preferred", [](int i) { return i / 2; }, "i"_a);
184  m.def(
185  "ints_only", [](int i) { return i / 2; }, "i"_a.noconvert());
186 
187  // test_custom_caster_destruction
188  // Test that `take_ownership` works on types with a custom type caster when given a pointer
189 
190  // default policy: don't take ownership:
191  m.def("custom_caster_no_destroy", []() {
192  static auto *dt = new DestructionTester();
193  return dt;
194  });
195 
196  m.def(
197  "custom_caster_destroy",
198  []() { return new DestructionTester(); },
199  py::return_value_policy::take_ownership); // Takes ownership: destroy when finished
200  m.def(
201  "custom_caster_destroy_const",
202  []() -> const DestructionTester * { return new DestructionTester(); },
203  py::return_value_policy::take_ownership); // Likewise (const doesn't inhibit destruction)
204  m.def("destruction_tester_cstats",
205  &ConstructorStats::get<DestructionTester>,
206  py::return_value_policy::reference);
207 
208  m.def("other_lib_type", [](other_lib::MyType x) { return x; });
209 }
Matrix3f m
static handle cast(const ArgInspector1 &src, return_value_policy, handle)
static py_::handle cast(const MyType &, py_::return_value_policy, py_::handle)
TEST_SUBMODULE(custom_type_casters, m)
static handle cast(const ArgAlwaysConverts &, return_value_policy, handle)
Scalar * b
Definition: benchVecAdd.cpp:17
bool load(py_::handle, bool)
DestructionTester(const DestructionTester &)
DestructionTester & operator=(DestructionTester &&) noexcept
Scalar Scalar * c
Definition: benchVecAdd.cpp:17
void print_destroyed(T *inst, Values &&...values)
void print_copy_assigned(T *inst, Values &&...values)
void print_copy_created(T *inst, Values &&...values)
Definition: cast.h:1238
DestructionTester & operator=(const DestructionTester &)
void g(const string &key, int i)
Definition: testBTree.cpp:41
static handle cast(const DestructionTester &, return_value_policy, handle)
const double dt
void print_default_created(T *inst, Values &&...values)
void print_move_assigned(T *inst, Values &&...values)
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const ArgReturnType arg() const
Point2(* f)(const Point3 &, OptionalJacobian< 2, 3 >)
DestructionTester(DestructionTester &&) noexcept
const double h
constexpr descr< N - 1 > _(char const (&text)[N])
Definition: descr.h:109
static handle cast(const ArgInspector2 &src, return_value_policy, handle)
void print_move_created(T *inst, Values &&...values)
set noclip points set clip one set noclip two set bar set border lt lw set xdata set ydata set zdata set x2data set y2data set boxwidth set dummy x
constexpr descr< N - 1 > const_name(char const (&text)[N])
Definition: descr.h:60
return_value_policy
Approach used to cast a previously unknown C++ instance into a Python object.
#define PYBIND11_TYPE_CASTER(type, py_name)
Definition: cast.h:82
static BinaryMeasurement< Rot3 > convert(const BetweenFactor< Pose3 >::shared_ptr &f)


gtsam
Author(s):
autogenerated on Tue Jul 4 2023 02:37:45