1
0

function.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. #include "test.h"
  2. namespace {
  3. TEST_F(PYBIND11_TEST, vectorcall) {
  4. auto m = py::module::__main__();
  5. py::exec(R"(
  6. def add(a, b):
  7. return a + b
  8. )");
  9. // position only
  10. EXPECT_CAST_EQ(m.attr("add")(1, 2), 3);
  11. // FIXME: pkpy does not support such calling.
  12. // keyword only
  13. // EXPECT_CAST_EQ(m.attr("add")(py::arg("a") = 1, py::arg("b") = 2), 3);
  14. // mix
  15. // EXPECT_CAST_EQ(m.attr("add")(1, py::arg("b") = 2), 3);
  16. py::exec(R"(
  17. def add2(a, *args):
  18. return a + sum(args)
  19. )");
  20. EXPECT_CAST_EQ(m.attr("add2")(1, 2, 3, 4), 10);
  21. EXPECT_EQ(py::type::of<py::tuple>()(py::eval("[1, 2, 3]")), py::eval("(1, 2, 3)"));
  22. EXPECT_EQ(py::type::of<py::list>()(py::eval("(1, 2, 3)")), py::eval("[1, 2, 3]"));
  23. }
  24. TEST_F(PYBIND11_TEST, constructor) {
  25. auto m = py::module::__main__();
  26. struct Point {
  27. int x, y;
  28. Point(int x, int y) : x(x), y(y) {}
  29. bool operator== (const Point& p) const { return x == p.x && y == p.y; }
  30. };
  31. py::class_<Point>(m, "Point")
  32. .def(py::init<int, int>(), py::arg("x") = 1, py::arg("y") = 2)
  33. .def(py::init([](py::tuple tuple) {
  34. return Point(tuple[0].cast<int>(), tuple[1].cast<int>());
  35. }))
  36. .def("__eq__", &Point::operator==);
  37. EXPECT_EVAL_EQ("Point()", Point(1, 2));
  38. EXPECT_EVAL_EQ("Point(3)", Point(3, 2));
  39. EXPECT_EVAL_EQ("Point(3, 4)", Point(3, 4));
  40. EXPECT_EVAL_EQ("Point((3, 4))", Point(3, 4));
  41. }
  42. TEST_F(PYBIND11_TEST, args) {
  43. auto m = py::module::__main__();
  44. // test for binding function with args
  45. m.def("sum", [](py::args args) {
  46. int sum = 0;
  47. for(auto arg: args) {
  48. sum += arg.cast<int>();
  49. }
  50. return sum;
  51. });
  52. EXPECT_EVAL_EQ("sum(1, 2, 3)", 6);
  53. }
  54. TEST_F(PYBIND11_TEST, kwargs) {
  55. auto m = py::module::__main__();
  56. // test for binding function with kwargs
  57. m.def("cal", [](py::kwargs kwargs) {
  58. int sum = kwargs["a"].cast<int>() + kwargs["b"].cast<int>() * kwargs["c"].cast<int>();
  59. return sum;
  60. });
  61. EXPECT_EVAL_EQ("cal(a=1, b=2, c=3)", 7);
  62. }
  63. TEST_F(PYBIND11_TEST, defaults) {
  64. auto m = py::module::__main__();
  65. // test for binding function with defaults
  66. m.def(
  67. "cal",
  68. [](int a, int b = 2, int c = 3) {
  69. return a + b * c;
  70. },
  71. py::arg("a"),
  72. py::arg("b") = 2,
  73. py::arg("c") = 3);
  74. EXPECT_EVAL_EQ("cal(1)", 7); // a = 1, b = 2, c = 3
  75. EXPECT_EVAL_EQ("cal(1, 4)", 13); // a = 1, b = 4, c = 3
  76. EXPECT_EVAL_EQ("cal(1, 4, 5)", 21); // a = 1, b = 4, c = 5
  77. EXPECT_EVAL_EQ("cal(2, c=6)", 14); // a = 2, b = 2, c = 6
  78. EXPECT_EVAL_EQ("cal(2, b=4, c=6)", 26); // a = 2, b = 4, c = 6
  79. }
  80. TEST_F(PYBIND11_TEST, defaults_with_args) {
  81. auto m = py::module::__main__();
  82. // test for binding function with defaults
  83. m.def(
  84. "cal",
  85. [](int a, int b, int c, py::args args) {
  86. int sum = a + b + c;
  87. for(auto arg: args) {
  88. sum += arg.cast<int>();
  89. }
  90. return sum;
  91. },
  92. py::arg("a"),
  93. py::arg("b") = 2,
  94. py::arg("c") = 3);
  95. EXPECT_EVAL_EQ("cal(1)", 6); // a = 1, b = 2, c = 3
  96. EXPECT_EVAL_EQ("cal(1, 4)", 8); // a = 1, b = 4, c = 3
  97. EXPECT_EVAL_EQ("cal(1, 4, 5)", 10); // a = 1, b = 4, c = 5
  98. EXPECT_EVAL_EQ("cal(1, 4, 5, 6)", 16); // a = 1, b = 4, c = 5, args = (6)
  99. EXPECT_EVAL_EQ("cal(1, 4, 5, 6, 7)", 23); // a = 1, b = 4, c = 5, args = (6, 7)
  100. }
  101. TEST_F(PYBIND11_TEST, default_with_args_and_kwargs) {
  102. auto m = py::module::__main__();
  103. // test for binding function with defaults
  104. m.def(
  105. "cal",
  106. [](int a, int b, int c, py::args args, py::kwargs kwargs) {
  107. int sum = a + b + c;
  108. for(auto arg: args) {
  109. sum += arg.cast<int>();
  110. }
  111. for(auto item: kwargs) {
  112. sum += item.second.cast<int>();
  113. }
  114. return sum;
  115. },
  116. py::arg("a"),
  117. py::arg("b") = 2,
  118. py::arg("c") = 3);
  119. EXPECT_EVAL_EQ("cal(1)", 6); // a = 1, b = 2, c = 3
  120. EXPECT_EVAL_EQ("cal(1, 4)", 8); // a = 1, b = 4, c = 3
  121. EXPECT_EVAL_EQ("cal(1, 4, 5)", 10); // a = 1, b = 4, c = 5
  122. EXPECT_EVAL_EQ("cal(1, 4, 5, 6)", 16); // a = 1, b = 4, c = 5, args = (6)
  123. EXPECT_EVAL_EQ("cal(1, 4, 5, 6, 7)", 23); // a = 1, b = 4, c = 5, args = (6, 7)
  124. EXPECT_EVAL_EQ("cal(1, 4, 5, d=6, e=7)", 23); // a = 1, b = 4, c = 5, kwargs = {d=6, e=7}
  125. EXPECT_EVAL_EQ("cal(1, d=6, e=7)", 19); // a = 1, b = 2, c = 3, kwargs = {d=6, e=7}
  126. EXPECT_EVAL_EQ("cal(1)", 6); // a = 1, b = 2, c = 3
  127. EXPECT_EVAL_EQ("cal(1, b=4)", 8); // a = 1, b = 4, c = 3
  128. EXPECT_EVAL_EQ("cal(1, c=5)", 8); // a = 1, b = 2, c = 5
  129. EXPECT_EVAL_EQ("cal(1, 4, d=6)", 14); // a = 1, b = 4, c = 3, kwargs = {d=6}
  130. EXPECT_EVAL_EQ("cal(1, c=5, d=6)", 14); // a = 1, b = 2, c = 5, kwargs = {d=6}
  131. EXPECT_EVAL_EQ("cal(1, 4, 5, d=6)", 16); // a = 1, b = 4, c = 5, kwargs = {d=6}
  132. EXPECT_EVAL_EQ("cal(1, 4, 5)", 10); // a = 1, b = 4, c = 5, args = (), kwargs = {}
  133. EXPECT_EVAL_EQ("cal(1, 4, 5, *[], **{})", 10); // a = 1, b = 4, c = 5, args = (), kwargs = {}
  134. EXPECT_EVAL_EQ("cal(1, 4, 5, 6, 7, d=8, e=9)", 40); // a = 1, b = 4, c = 5, args = (6, 7), kwargs = {d=8, e=9}
  135. struct Point {
  136. int x, y;
  137. Point(int x, int y) : x(x), y(y) {}
  138. int sum(int x = 1, int y = 2) { return this->x + this->y + x + y; }
  139. };
  140. py::class_<Point>(m, "Point")
  141. .def(py::init<int, int>()) //
  142. .def("sum", &Point::sum, py::arg("x") = 1, py::arg("y") = 2);
  143. EXPECT_EVAL_EQ("Point(1, 2).sum()", 6); // x = 1, y = 2
  144. EXPECT_EVAL_EQ("Point(1, 2).sum(3)", 8); // x = 3, y = 2
  145. EXPECT_EVAL_EQ("Point(1, 2).sum(3, 4)", 10); // x = 3, y = 4
  146. }
  147. TEST_F(PYBIND11_TEST, overload) {
  148. auto m = py::module::__main__();
  149. // test for binding function with overloads
  150. m.def("cal", [](int a, int b) {
  151. return a + b;
  152. });
  153. m.def("cal", [](int a, int b, int c) {
  154. return a + b + c;
  155. });
  156. EXPECT_EVAL_EQ("cal(1, 2)", 3);
  157. EXPECT_EVAL_EQ("cal(1, 2, 3)", 6);
  158. struct Point {
  159. static int sum(int x) { return x; }
  160. static int sum(int x, int y) { return x + y; }
  161. };
  162. py::class_<Point>(m, "Point")
  163. .def_static("sum", py::overload_cast<int>(&Point::sum))
  164. .def_static("sum", py::overload_cast<int, int>(&Point::sum));
  165. EXPECT_EVAL_EQ("Point.sum(1)", 1);
  166. EXPECT_EVAL_EQ("Point.sum(1, 2)", 3);
  167. }
  168. TEST_F(PYBIND11_TEST, return_value_policy) {
  169. static int copy_constructor_calls = 0;
  170. static int move_constructor_calls = 0;
  171. static int destructor_calls = 0;
  172. struct Point {
  173. int x, y;
  174. Point(int x, int y) : x(x), y(y) {}
  175. Point(const Point& p) : x(p.x), y(p.y) { copy_constructor_calls++; }
  176. Point(Point&& p) : x(p.x), y(p.y) { move_constructor_calls++; }
  177. ~Point() { destructor_calls++; }
  178. static Point& make_point() {
  179. static Point p(1, 2);
  180. return p;
  181. }
  182. static Point& new_point() { return *new Point(1, 2); }
  183. bool operator== (const Point& p) const { return x == p.x && y == p.y; }
  184. };
  185. py::finalize(true);
  186. auto test = [](py::return_value_policy policy, auto bound_fn, auto fn) {
  187. py::initialize();
  188. copy_constructor_calls = 0;
  189. move_constructor_calls = 0;
  190. destructor_calls = 0;
  191. auto m = py::module::__main__();
  192. py::class_<Point>(m, "Point")
  193. .def(py::init<int, int>())
  194. .def_readwrite("x", &Point::x)
  195. .def_readwrite("y", &Point::y)
  196. .def("__eq__", &Point::operator==);
  197. m.def("make_point", bound_fn, policy);
  198. EXPECT_EVAL_EQ("make_point()", Point::make_point());
  199. py::finalize(true);
  200. fn();
  201. };
  202. test(py::return_value_policy::reference, &Point::make_point, []() {
  203. EXPECT_EQ(copy_constructor_calls, 0);
  204. EXPECT_EQ(move_constructor_calls, 0);
  205. EXPECT_EQ(destructor_calls, 0);
  206. });
  207. test(py::return_value_policy::copy, &Point::make_point, []() {
  208. EXPECT_EQ(copy_constructor_calls, 1);
  209. EXPECT_EQ(move_constructor_calls, 0);
  210. EXPECT_EQ(destructor_calls, 1);
  211. });
  212. test(py::return_value_policy::move, &Point::make_point, []() {
  213. EXPECT_EQ(copy_constructor_calls, 0);
  214. EXPECT_EQ(move_constructor_calls, 1);
  215. EXPECT_EQ(destructor_calls, 1);
  216. });
  217. test(py::return_value_policy::take_ownership, &Point::new_point, []() {
  218. EXPECT_EQ(copy_constructor_calls, 0);
  219. EXPECT_EQ(move_constructor_calls, 0);
  220. EXPECT_EQ(destructor_calls, 1);
  221. });
  222. }
  223. TEST_F(PYBIND11_TEST, default_return_value_policy) {
  224. static int copy_constructor_calls = 0;
  225. static int move_constructor_calls = 0;
  226. static int destructor_calls = 0;
  227. struct Point {
  228. int x, y;
  229. Point(int x, int y) : x(x), y(y) {}
  230. Point(const Point& p) : x(p.x), y(p.y) { copy_constructor_calls++; }
  231. Point(Point&& p) : x(p.x), y(p.y) { move_constructor_calls++; }
  232. ~Point() { destructor_calls++; }
  233. bool operator== (const Point& p) const { return x == p.x && y == p.y; }
  234. };
  235. auto m = py::module::__main__();
  236. py::class_<Point>(m, "Point")
  237. .def(py::init<int, int>())
  238. .def_readwrite("x", &Point::x)
  239. .def_readwrite("y", &Point::y)
  240. .def("__eq__", &Point::operator==);
  241. // for function return value policy
  242. // if return type is lvalue reference, policy is copy
  243. m.def("make_point2", []() -> Point& {
  244. static Point p(1, 2);
  245. return p;
  246. });
  247. py::exec("p2 = make_point2()");
  248. EXPECT_EQ(copy_constructor_calls, 1);
  249. EXPECT_EQ(move_constructor_calls, 0);
  250. // if return type is rvalue reference, policy is move
  251. m.def("make_point3", []() -> Point&& {
  252. static Point p(1, 2);
  253. return std::move(p);
  254. });
  255. py::exec("p3 = make_point3()");
  256. EXPECT_EQ(copy_constructor_calls, 1);
  257. EXPECT_EQ(move_constructor_calls, 1);
  258. // if return type is pointer, policy is take_ownership
  259. m.def("make_point4", []() -> Point* {
  260. return new Point(1, 2);
  261. });
  262. py::exec("p4 = make_point4()");
  263. EXPECT_EQ(copy_constructor_calls, 1);
  264. EXPECT_EQ(move_constructor_calls, 1);
  265. py::finalize(true);
  266. EXPECT_EQ(destructor_calls, 3);
  267. }
  268. TEST_F(PYBIND11_TEST, lambda) {
  269. auto m = py::module::__main__();
  270. static int destructor_calls = 0;
  271. struct NotTrivial {
  272. int data;
  273. int operator() (int x, int y) { return x + y + data; }
  274. ~NotTrivial() { destructor_calls++; }
  275. };
  276. struct NotSmall {
  277. size_t a;
  278. size_t b;
  279. size_t c;
  280. size_t d;
  281. size_t operator() (size_t x, size_t y) { return x + y + a + b + c + d; }
  282. ~NotSmall() { destructor_calls++; }
  283. };
  284. // test for binding lambda
  285. m.def("cal", NotTrivial{3});
  286. m.def("cal2", NotSmall{3, 4, 5, 6});
  287. EXPECT_EVAL_EQ("cal(1, 2)", 6);
  288. EXPECT_EVAL_EQ("cal2(1, 2)", 21);
  289. py::finalize(true);
  290. EXPECT_EQ(destructor_calls, 4);
  291. }
  292. int add(int a, int b) { return a + b; }
  293. int add(int a, int b, int c) { return a + b + c; }
  294. TEST_F(PYBIND11_TEST, overload_cast) {
  295. auto m = py::module::__main__();
  296. m.def("add", py::overload_cast<int, int>(add));
  297. m.def("add", py::overload_cast<int, int, int>(add));
  298. EXPECT_EVAL_EQ("add(1, 2)", 3);
  299. EXPECT_EVAL_EQ("add(1, 2, 3)", 6);
  300. struct X {
  301. X() {}
  302. int add(int a, int b) { return a + b; }
  303. int add(int a, int b, int c) { return a + b + c; }
  304. };
  305. py::class_<X>(m, "X")
  306. .def(py::init<>())
  307. .def("add", py::overload_cast<int, int>(&X::add))
  308. .def("add", py::overload_cast<int, int, int>(&X::add));
  309. EXPECT_EVAL_EQ("X().add(1, 2)", 3);
  310. EXPECT_EVAL_EQ("X().add(1, 2, 3)", 6);
  311. }
  312. } // namespace