| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402 |
- #include "test.h"
- namespace {
- TEST_F(PYBIND11_TEST, vectorcall) {
- auto m = py::module::__main__();
- py::exec(R"(
- def add(a, b):
- return a + b
- )");
- // position only
- EXPECT_CAST_EQ(m.attr("add")(1, 2), 3);
- // FIXME: pkpy does not support such calling.
- // keyword only
- // EXPECT_CAST_EQ(m.attr("add")(py::arg("a") = 1, py::arg("b") = 2), 3);
- // mix
- // EXPECT_CAST_EQ(m.attr("add")(1, py::arg("b") = 2), 3);
- py::exec(R"(
- def add2(a, *args):
- return a + sum(args)
- )");
- EXPECT_CAST_EQ(m.attr("add2")(1, 2, 3, 4), 10);
- EXPECT_EQ(py::type::of<py::tuple>()(py::eval("[1, 2, 3]")), py::eval("(1, 2, 3)"));
- EXPECT_EQ(py::type::of<py::list>()(py::eval("(1, 2, 3)")), py::eval("[1, 2, 3]"));
- }
- TEST_F(PYBIND11_TEST, constructor) {
- auto m = py::module::__main__();
- struct Point {
- int x, y;
- Point(int x, int y) : x(x), y(y) {}
- bool operator== (const Point& p) const { return x == p.x && y == p.y; }
- };
- py::class_<Point>(m, "Point")
- .def(py::init<int, int>(), py::arg("x") = 1, py::arg("y") = 2)
- .def(py::init([](py::tuple tuple) {
- return Point(tuple[0].cast<int>(), tuple[1].cast<int>());
- }))
- .def("__eq__", &Point::operator==);
- EXPECT_EVAL_EQ("Point()", Point(1, 2));
- EXPECT_EVAL_EQ("Point(3)", Point(3, 2));
- EXPECT_EVAL_EQ("Point(3, 4)", Point(3, 4));
- EXPECT_EVAL_EQ("Point((3, 4))", Point(3, 4));
- }
- TEST_F(PYBIND11_TEST, args) {
- auto m = py::module::__main__();
- // test for binding function with args
- m.def("sum", [](py::args args) {
- int sum = 0;
- for(auto arg: args) {
- sum += arg.cast<int>();
- }
- return sum;
- });
- EXPECT_EVAL_EQ("sum(1, 2, 3)", 6);
- }
- TEST_F(PYBIND11_TEST, kwargs) {
- auto m = py::module::__main__();
- // test for binding function with kwargs
- m.def("cal", [](py::kwargs kwargs) {
- int sum = kwargs["a"].cast<int>() + kwargs["b"].cast<int>() * kwargs["c"].cast<int>();
- return sum;
- });
- EXPECT_EVAL_EQ("cal(a=1, b=2, c=3)", 7);
- }
- TEST_F(PYBIND11_TEST, defaults) {
- auto m = py::module::__main__();
- // test for binding function with defaults
- m.def(
- "cal",
- [](int a, int b = 2, int c = 3) {
- return a + b * c;
- },
- py::arg("a"),
- py::arg("b") = 2,
- py::arg("c") = 3);
- EXPECT_EVAL_EQ("cal(1)", 7); // a = 1, b = 2, c = 3
- EXPECT_EVAL_EQ("cal(1, 4)", 13); // a = 1, b = 4, c = 3
- EXPECT_EVAL_EQ("cal(1, 4, 5)", 21); // a = 1, b = 4, c = 5
- EXPECT_EVAL_EQ("cal(2, c=6)", 14); // a = 2, b = 2, c = 6
- EXPECT_EVAL_EQ("cal(2, b=4, c=6)", 26); // a = 2, b = 4, c = 6
- }
- TEST_F(PYBIND11_TEST, defaults_with_args) {
- auto m = py::module::__main__();
- // test for binding function with defaults
- m.def(
- "cal",
- [](int a, int b, int c, py::args args) {
- int sum = a + b + c;
- for(auto arg: args) {
- sum += arg.cast<int>();
- }
- return sum;
- },
- py::arg("a"),
- py::arg("b") = 2,
- py::arg("c") = 3);
- EXPECT_EVAL_EQ("cal(1)", 6); // a = 1, b = 2, c = 3
- EXPECT_EVAL_EQ("cal(1, 4)", 8); // a = 1, b = 4, c = 3
- EXPECT_EVAL_EQ("cal(1, 4, 5)", 10); // a = 1, b = 4, c = 5
- EXPECT_EVAL_EQ("cal(1, 4, 5, 6)", 16); // a = 1, b = 4, c = 5, args = (6)
- EXPECT_EVAL_EQ("cal(1, 4, 5, 6, 7)", 23); // a = 1, b = 4, c = 5, args = (6, 7)
- }
- TEST_F(PYBIND11_TEST, default_with_args_and_kwargs) {
- auto m = py::module::__main__();
- // test for binding function with defaults
- m.def(
- "cal",
- [](int a, int b, int c, py::args args, py::kwargs kwargs) {
- int sum = a + b + c;
- for(auto arg: args) {
- sum += arg.cast<int>();
- }
- for(auto item: kwargs) {
- sum += item.second.cast<int>();
- }
- return sum;
- },
- py::arg("a"),
- py::arg("b") = 2,
- py::arg("c") = 3);
- EXPECT_EVAL_EQ("cal(1)", 6); // a = 1, b = 2, c = 3
- EXPECT_EVAL_EQ("cal(1, 4)", 8); // a = 1, b = 4, c = 3
- EXPECT_EVAL_EQ("cal(1, 4, 5)", 10); // a = 1, b = 4, c = 5
- EXPECT_EVAL_EQ("cal(1, 4, 5, 6)", 16); // a = 1, b = 4, c = 5, args = (6)
- EXPECT_EVAL_EQ("cal(1, 4, 5, 6, 7)", 23); // a = 1, b = 4, c = 5, args = (6, 7)
- EXPECT_EVAL_EQ("cal(1, 4, 5, d=6, e=7)", 23); // a = 1, b = 4, c = 5, kwargs = {d=6, e=7}
- EXPECT_EVAL_EQ("cal(1, d=6, e=7)", 19); // a = 1, b = 2, c = 3, kwargs = {d=6, e=7}
- EXPECT_EVAL_EQ("cal(1)", 6); // a = 1, b = 2, c = 3
- EXPECT_EVAL_EQ("cal(1, b=4)", 8); // a = 1, b = 4, c = 3
- EXPECT_EVAL_EQ("cal(1, c=5)", 8); // a = 1, b = 2, c = 5
- EXPECT_EVAL_EQ("cal(1, 4, d=6)", 14); // a = 1, b = 4, c = 3, kwargs = {d=6}
- EXPECT_EVAL_EQ("cal(1, c=5, d=6)", 14); // a = 1, b = 2, c = 5, kwargs = {d=6}
- EXPECT_EVAL_EQ("cal(1, 4, 5, d=6)", 16); // a = 1, b = 4, c = 5, kwargs = {d=6}
- EXPECT_EVAL_EQ("cal(1, 4, 5)", 10); // a = 1, b = 4, c = 5, args = (), kwargs = {}
- EXPECT_EVAL_EQ("cal(1, 4, 5, *[], **{})", 10); // a = 1, b = 4, c = 5, args = (), kwargs = {}
- 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}
- struct Point {
- int x, y;
- Point(int x, int y) : x(x), y(y) {}
- int sum(int x = 1, int y = 2) { return this->x + this->y + x + y; }
- };
- py::class_<Point>(m, "Point")
- .def(py::init<int, int>()) //
- .def("sum", &Point::sum, py::arg("x") = 1, py::arg("y") = 2);
- EXPECT_EVAL_EQ("Point(1, 2).sum()", 6); // x = 1, y = 2
- EXPECT_EVAL_EQ("Point(1, 2).sum(3)", 8); // x = 3, y = 2
- EXPECT_EVAL_EQ("Point(1, 2).sum(3, 4)", 10); // x = 3, y = 4
- }
- TEST_F(PYBIND11_TEST, overload) {
- auto m = py::module::__main__();
- // test for binding function with overloads
- m.def("cal", [](int a, int b) {
- return a + b;
- });
- m.def("cal", [](int a, int b, int c) {
- return a + b + c;
- });
- EXPECT_EVAL_EQ("cal(1, 2)", 3);
- EXPECT_EVAL_EQ("cal(1, 2, 3)", 6);
- }
- TEST_F(PYBIND11_TEST, return_value_policy) {
- static int copy_constructor_calls = 0;
- static int move_constructor_calls = 0;
- static int destructor_calls = 0;
- struct Point {
- int x, y;
- Point(int x, int y) : x(x), y(y) {}
- Point(const Point& p) : x(p.x), y(p.y) { copy_constructor_calls++; }
- Point(Point&& p) : x(p.x), y(p.y) { move_constructor_calls++; }
- ~Point() { destructor_calls++; }
- static Point& make_point() {
- static Point p(1, 2);
- return p;
- }
- static Point& new_point() { return *new Point(1, 2); }
- bool operator== (const Point& p) const { return x == p.x && y == p.y; }
- };
- py::finalize(true);
- auto test = [](py::return_value_policy policy, auto bound_fn, auto fn) {
- py::initialize();
- copy_constructor_calls = 0;
- move_constructor_calls = 0;
- destructor_calls = 0;
- auto m = py::module::__main__();
- py::class_<Point>(m, "Point")
- .def(py::init<int, int>())
- .def_readwrite("x", &Point::x)
- .def_readwrite("y", &Point::y)
- .def("__eq__", &Point::operator==);
- m.def("make_point", bound_fn, policy);
- EXPECT_EVAL_EQ("make_point()", Point::make_point());
- py::finalize(true);
- fn();
- };
- test(py::return_value_policy::reference, &Point::make_point, []() {
- EXPECT_EQ(copy_constructor_calls, 0);
- EXPECT_EQ(move_constructor_calls, 0);
- EXPECT_EQ(destructor_calls, 0);
- });
- test(py::return_value_policy::copy, &Point::make_point, []() {
- EXPECT_EQ(copy_constructor_calls, 1);
- EXPECT_EQ(move_constructor_calls, 0);
- EXPECT_EQ(destructor_calls, 1);
- });
- test(py::return_value_policy::move, &Point::make_point, []() {
- EXPECT_EQ(copy_constructor_calls, 0);
- EXPECT_EQ(move_constructor_calls, 1);
- EXPECT_EQ(destructor_calls, 1);
- });
- test(py::return_value_policy::take_ownership, &Point::new_point, []() {
- EXPECT_EQ(copy_constructor_calls, 0);
- EXPECT_EQ(move_constructor_calls, 0);
- EXPECT_EQ(destructor_calls, 1);
- });
- }
- TEST_F(PYBIND11_TEST, default_return_value_policy) {
- static int copy_constructor_calls = 0;
- static int move_constructor_calls = 0;
- static int destructor_calls = 0;
- struct Point {
- int x, y;
- Point(int x, int y) : x(x), y(y) {}
- Point(const Point& p) : x(p.x), y(p.y) { copy_constructor_calls++; }
- Point(Point&& p) : x(p.x), y(p.y) { move_constructor_calls++; }
- ~Point() { destructor_calls++; }
- bool operator== (const Point& p) const { return x == p.x && y == p.y; }
- };
- auto m = py::module::__main__();
- py::class_<Point>(m, "Point")
- .def(py::init<int, int>())
- .def_readwrite("x", &Point::x)
- .def_readwrite("y", &Point::y)
- .def("__eq__", &Point::operator==);
- // for function return value policy
- // if return type is lvalue reference, policy is copy
- m.def("make_point2", []() -> Point& {
- static Point p(1, 2);
- return p;
- });
- py::exec("p2 = make_point2()");
- EXPECT_EQ(copy_constructor_calls, 1);
- EXPECT_EQ(move_constructor_calls, 0);
- // if return type is rvalue reference, policy is move
- m.def("make_point3", []() -> Point&& {
- static Point p(1, 2);
- return std::move(p);
- });
- py::exec("p3 = make_point3()");
- EXPECT_EQ(copy_constructor_calls, 1);
- EXPECT_EQ(move_constructor_calls, 1);
- // if return type is pointer, policy is take_ownership
- m.def("make_point4", []() -> Point* {
- return new Point(1, 2);
- });
- py::exec("p4 = make_point4()");
- EXPECT_EQ(copy_constructor_calls, 1);
- EXPECT_EQ(move_constructor_calls, 1);
- py::finalize(true);
- EXPECT_EQ(destructor_calls, 3);
- }
- TEST_F(PYBIND11_TEST, lambda) {
- auto m = py::module::__main__();
- static int destructor_calls = 0;
- struct NotTrivial {
- int data;
- int operator() (int x, int y) { return x + y + data; }
- ~NotTrivial() { destructor_calls++; }
- };
- struct NotSmall {
- size_t a;
- size_t b;
- size_t c;
- size_t d;
- size_t operator() (size_t x, size_t y) { return x + y + a + b + c + d; }
- ~NotSmall() { destructor_calls++; }
- };
- // test for binding lambda
- m.def("cal", NotTrivial{3});
- m.def("cal2", NotSmall{3, 4, 5, 6});
- EXPECT_EVAL_EQ("cal(1, 2)", 6);
- EXPECT_EVAL_EQ("cal2(1, 2)", 21);
- py::finalize(true);
- EXPECT_EQ(destructor_calls, 4);
- }
- int add(int a, int b) { return a + b; }
- int add(int a, int b, int c) { return a + b + c; }
- TEST_F(PYBIND11_TEST, overload_cast) {
- auto m = py::module::__main__();
- m.def("add", py::overload_cast<int, int>(add));
- m.def("add", py::overload_cast<int, int, int>(add));
- EXPECT_EVAL_EQ("add(1, 2)", 3);
- EXPECT_EVAL_EQ("add(1, 2, 3)", 6);
- struct X {
- X() {}
- int add(int a, int b) { return a + b; }
- int add(int a, int b, int c) { return a + b + c; }
- };
- py::class_<X>(m, "X")
- .def(py::init<>())
- .def("add", py::overload_cast<int, int>(&X::add))
- .def("add", py::overload_cast<int, int, int>(&X::add));
- EXPECT_EVAL_EQ("X().add(1, 2)", 3);
- EXPECT_EVAL_EQ("X().add(1, 2, 3)", 6);
- }
- } // namespace
|