| /** |
| * This file contains the pybind11 reference implementation for the stugen tests, |
| * and was originally inspired by: |
| * |
| * https://github.com/sizmailov/pybind11-mypy-demo |
| * |
| * Copyright (c) 2016 The Pybind Development Team, All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright notice, this |
| * list of conditions and the following disclaimer. |
| * |
| * 2. Redistributions in binary form must reproduce the above copyright notice, |
| * this list of conditions and the following disclaimer in the documentation |
| * and/or other materials provided with the distribution. |
| * |
| * 3. Neither the name of the copyright holder nor the names of its contributors |
| * may be used to endorse or promote products derived from this software |
| * without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
| * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE |
| * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
| * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
| * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
| * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| * |
| * You are under no obligation whatsoever to provide any bug fixes, patches, or |
| * upgrades to the features, functionality or performance of the source code |
| * ("Enhancements") to anyone; however, if you choose to make your Enhancements |
| * available either publicly, or directly to the author of this software, without |
| * imposing a separate written license agreement for such Enhancements, then you |
| * hereby grant the following license: a non-exclusive, royalty-free perpetual |
| * license to install, use, modify, prepare derivative works, incorporate into |
| * other computer software, distribute, and sublicense such enhancements or |
| * derivative works thereof, in binary and source code form. |
| */ |
| |
| #include <cmath> |
| #include <filesystem> |
| #include <optional> |
| #include <utility> |
| #include <vector> |
| |
| #include <pybind11/pybind11.h> |
| #include <pybind11/stl.h> |
| #include <pybind11/stl/filesystem.h> |
| |
| namespace py = pybind11; |
| |
| // ---------------------------------------------------------------------------- |
| // Dedicated test cases |
| // ---------------------------------------------------------------------------- |
| |
| std::vector<float> funcReturningVector() |
| { |
| return std::vector<float>{1.0, 2.0, 3.0}; |
| } |
| |
| std::pair<int, float> funcReturningPair() |
| { |
| return std::pair{42, 1.0}; |
| } |
| |
| std::optional<int> funcReturningOptional() |
| { |
| return std::nullopt; |
| } |
| |
| std::filesystem::path funcReturningPath() |
| { |
| return std::filesystem::path{"foobar"}; |
| } |
| |
| namespace dummy_sub_namespace { |
| struct HasNoBinding{}; |
| } |
| |
| // We can enforce the case of an incomplete signature by referring to a type in |
| // some namespace that doesn't have a pybind11 binding. |
| dummy_sub_namespace::HasNoBinding funcIncompleteSignature() |
| { |
| return dummy_sub_namespace::HasNoBinding{}; |
| } |
| |
| struct TestStruct |
| { |
| int field_readwrite; |
| int field_readwrite_docstring; |
| int field_readonly; |
| }; |
| |
| struct StaticMethods |
| { |
| static int some_static_method(int a, int b) { return 42; } |
| static int overloaded_static_method(int value) { return 42; } |
| static double overloaded_static_method(double value) { return 1.0; } |
| }; |
| |
| // Bindings |
| |
| void bind_test_cases(py::module& m) { |
| m.def("func_returning_vector", &funcReturningVector); |
| m.def("func_returning_pair", &funcReturningPair); |
| m.def("func_returning_optional", &funcReturningOptional); |
| m.def("func_returning_path", &funcReturningPath); |
| |
| m.def("func_incomplete_signature", &funcIncompleteSignature); |
| |
| py::class_<TestStruct>(m, "TestStruct") |
| .def_readwrite("field_readwrite", &TestStruct::field_readwrite) |
| .def_readwrite("field_readwrite_docstring", &TestStruct::field_readwrite_docstring, "some docstring") |
| .def_property_readonly( |
| "field_readonly", |
| [](const TestStruct& x) { |
| return x.field_readonly; |
| }, |
| "some docstring"); |
| |
| // Static methods |
| py::class_<StaticMethods> pyStaticMethods(m, "StaticMethods"); |
| |
| pyStaticMethods |
| .def_static( |
| "some_static_method", |
| &StaticMethods::some_static_method, R"#(None)#", py::arg("a"), py::arg("b")) |
| .def_static( |
| "overloaded_static_method", |
| py::overload_cast<int>(&StaticMethods::overloaded_static_method), py::arg("value")) |
| .def_static( |
| "overloaded_static_method", |
| py::overload_cast<double>(&StaticMethods::overloaded_static_method), py::arg("value")); |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // Original demo |
| // ---------------------------------------------------------------------------- |
| |
| namespace demo { |
| |
| int answer() { |
| return 42; |
| } |
| |
| int sum(int a, int b) { |
| return a + b; |
| } |
| |
| double midpoint(double left, double right){ |
| return left + (right - left)/2; |
| } |
| |
| double weighted_midpoint(double left, double right, double alpha=0.5) { |
| return left + (right - left) * alpha; |
| } |
| |
| struct Point { |
| |
| enum class LengthUnit { |
| mm=0, |
| pixel, |
| inch |
| }; |
| |
| enum class AngleUnit { |
| radian=0, |
| degree |
| }; |
| |
| Point() : Point(0, 0) {} |
| Point(double x, double y) : x(x), y(y) {} |
| |
| static const Point origin; |
| static const Point x_axis; |
| static const Point y_axis; |
| |
| static LengthUnit length_unit; |
| static AngleUnit angle_unit; |
| |
| double length() const { |
| return std::sqrt(x * x + y * y); |
| } |
| |
| double distance_to(double other_x, double other_y) const { |
| double dx = x - other_x; |
| double dy = y - other_y; |
| return std::sqrt(dx*dx + dy*dy); |
| } |
| |
| double distance_to(const Point& other) const { |
| return distance_to(other.x, other.y); |
| } |
| |
| std::vector<double> as_vector() |
| { |
| return std::vector<double>{x, y}; |
| } |
| |
| double x, y; |
| }; |
| |
| const Point Point::origin = Point(0, 0); |
| const Point Point::x_axis = Point(1, 0); |
| const Point Point::y_axis = Point(0, 1); |
| |
| Point::LengthUnit Point::length_unit = Point::LengthUnit::mm; |
| Point::AngleUnit Point::angle_unit = Point::AngleUnit::radian; |
| |
| } // namespace: demo |
| |
| // Bindings |
| |
| void bind_demo(py::module& m) { |
| |
| using namespace demo; |
| |
| // Functions |
| m.def("answer", &answer, "answer docstring, with end quote\""); // tests explicit docstrings |
| m.def("sum", &sum, "multiline docstring test, edge case quotes \"\"\"'''"); |
| m.def("midpoint", &midpoint, py::arg("left"), py::arg("right")); |
| m.def("weighted_midpoint", weighted_midpoint, py::arg("left"), py::arg("right"), py::arg("alpha")=0.5); |
| |
| // Classes |
| py::class_<Point> pyPoint(m, "Point"); |
| py::enum_<Point::LengthUnit> pyLengthUnit(pyPoint, "LengthUnit"); |
| py::enum_<Point::AngleUnit> pyAngleUnit(pyPoint, "AngleUnit"); |
| |
| pyPoint |
| .def(py::init<>()) |
| .def(py::init<double, double>(), py::arg("x"), py::arg("y")) |
| .def("distance_to", py::overload_cast<double, double>(&Point::distance_to, py::const_), py::arg("x"), py::arg("y")) |
| .def("distance_to", py::overload_cast<const Point&>(&Point::distance_to, py::const_), py::arg("other")) |
| .def("as_list", &Point::as_vector) |
| .def_readwrite("x", &Point::x, "some docstring") |
| .def_property("y", |
| [](Point& self){ return self.y; }, |
| [](Point& self, double value){ self.y = value; } |
| ) |
| .def_property_readonly("length", &Point::length) |
| .def_property_readonly_static("x_axis", [](py::object cls){return Point::x_axis;}) |
| .def_property_readonly_static("y_axis", [](py::object cls){return Point::y_axis;}, "another docstring") |
| .def_readwrite_static("length_unit", &Point::length_unit) |
| .def_property_static("angle_unit", |
| [](py::object& /*cls*/){ return Point::angle_unit; }, |
| [](py::object& /*cls*/, Point::AngleUnit value){ Point::angle_unit = value; } |
| ); |
| |
| pyPoint.attr("origin") = Point::origin; |
| |
| pyLengthUnit |
| .value("mm", Point::LengthUnit::mm) |
| .value("pixel", Point::LengthUnit::pixel) |
| .value("inch", Point::LengthUnit::inch); |
| |
| pyAngleUnit |
| .value("radian", Point::AngleUnit::radian) |
| .value("degree", Point::AngleUnit::degree); |
| |
| // Module-level attributes |
| m.attr("PI") = std::acos(-1); |
| m.attr("__version__") = "0.0.1"; |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // Module entry point |
| // ---------------------------------------------------------------------------- |
| |
| PYBIND11_MODULE(pybind11_fixtures, m) { |
| bind_test_cases(m); |
| |
| auto demo = m.def_submodule("demo"); |
| bind_demo(demo); |
| } |