{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Classes and structs" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Exclude members and classes\n", "\n", "Sometimes, you may want to exclude classes and/or members from the bindings. Look at the example below for instructions:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", "\n", "
class FooDetails // A class that we want to exclude from the bindings\n",
" {\n",
" // ...\n",
" };\n",
"\n",
" struct Foo \n",
" {\n",
" int X = 0, Y = 1;\n",
"\n",
" FooDetails mDetails = {}; // A member that we would want to exclude from the bindings\n",
" };\n",
"
class Foo:\n",
" x: int = 0\n",
" y: int = 1\n",
"\n",
" def __init__(self, x: int = 0, y: int = 1) -> None:\n",
" """Auto-generated default constructor with named params"""\n",
" pass\n",
"
auto pyClassFoo =\n",
" py::class_<Foo>\n",
" (m, "Foo", "")\n",
" .def(py::init<>([](\n",
" int X = 0, int Y = 1)\n",
" {\n",
" auto r = std::make_unique<Foo>();\n",
" r->X = X;\n",
" r->Y = Y;\n",
" return r;\n",
" })\n",
" , py::arg("x") = 0, py::arg("y") = 1\n",
" )\n",
" .def_readwrite("x", &Foo::X, "")\n",
" .def_readwrite("y", &Foo::Y, "")\n",
" ;\n",
"
enum class Options { A, B };\n",
"\n",
" // A constructor with named params will be created for FooClass, \n",
" // since options.class_create_default_named_ctor__regex was filled\n",
" class FooClass { \n",
" public:\n",
" Options options = Options::A;\n",
" int a = 1;\n",
" };\n",
"\n",
" // A constructor with named params will be created for FooStruct\n",
" struct FooStruct { int X = 0, Y = 1; };\n",
"\n",
" // FooStruct has a default constructor, so no constructor with named params will be generated\n",
" struct FooStruct2 {\n",
" FooStruct2();\n",
" int X = 0, Y = 1;\n",
" };\n",
"
class Options(enum.Enum):\n",
" a = enum.auto() # (= 0)\n",
" b = enum.auto() # (= 1)\n",
"\n",
"class FooClass:\n",
" """ A constructor with named params will be created for FooClass,\n",
" since options.class_create_default_named_ctor__regex was filled\n",
" """\n",
" options: Options = Options.a\n",
" a: int = 1\n",
" def __init__(self, options: Options = Options.a, a: int = 1) -> None:\n",
" """Auto-generated default constructor with named params"""\n",
" pass\n",
"\n",
"class FooStruct:\n",
" """ A constructor with named params will be created for FooStruct"""\n",
" x: int = 0\n",
" y: int = 1\n",
" def __init__(self, x: int = 0, y: int = 1) -> None:\n",
" """Auto-generated default constructor with named params"""\n",
" pass\n",
"\n",
"class FooStruct2:\n",
" """ FooStruct has a default constructor, so no constructor with named params will be generated"""\n",
" def __init__(self) -> None:\n",
" pass\n",
" x: int = 0\n",
" y: int = 1\n",
"
py::enum_<Options>(m, "Options", py::arithmetic(), "")\n",
" .value("a", Options::A, "")\n",
" .value("b", Options::B, "");\n",
"\n",
"\n",
"auto pyClassFooClass =\n",
" py::class_<FooClass>\n",
" (m, "FooClass", " A constructor with named params will be created for FooClass,\\n since options.class_create_default_named_ctor__regex was filled")\n",
" .def(py::init<>([](\n",
" Options options = Options::A, int a = 1)\n",
" {\n",
" auto r = std::make_unique<FooClass>();\n",
" r->options = options;\n",
" r->a = a;\n",
" return r;\n",
" })\n",
" , py::arg("options") = Options::A, py::arg("a") = 1\n",
" )\n",
" .def_readwrite("options", &FooClass::options, "")\n",
" .def_readwrite("a", &FooClass::a, "")\n",
" ;\n",
"\n",
"\n",
"auto pyClassFooStruct =\n",
" py::class_<FooStruct>\n",
" (m, "FooStruct", "A constructor with named params will be created for FooStruct")\n",
" .def(py::init<>([](\n",
" int X = 0, int Y = 1)\n",
" {\n",
" auto r = std::make_unique<FooStruct>();\n",
" r->X = X;\n",
" r->Y = Y;\n",
" return r;\n",
" })\n",
" , py::arg("x") = 0, py::arg("y") = 1\n",
" )\n",
" .def_readwrite("x", &FooStruct::X, "")\n",
" .def_readwrite("y", &FooStruct::Y, "")\n",
" ;\n",
"\n",
"\n",
"auto pyClassFooStruct2 =\n",
" py::class_<FooStruct2>\n",
" (m, "FooStruct2", "FooStruct has a default constructor, so no constructor with named params will be generated")\n",
" .def(py::init<>())\n",
" .def_readwrite("x", &FooStruct2::X, "")\n",
" .def_readwrite("y", &FooStruct2::Y, "")\n",
" ;\n",
"
class A {\n",
"protected:\n",
" int foo() const { return 42; }\n",
"};\n",
"
class A:\n",
" def __init__(self) -> None:\n",
" """Autogenerated default constructor"""\n",
" pass\n",
"\n",
" # <protected_methods>\n",
" def foo(self) -> int:\n",
" pass\n",
" # </protected_methods>\n",
"
auto pyClassA =\n",
" py::class_<A>\n",
" (m, "A", "")\n",
" .def(py::init<>()) // implicit default constructor\n",
" .def("foo",\n",
" &A_publicist::foo)\n",
" ;\n",
"
// helper type for exposing protected functions\n",
"class A_publicist : public A\n",
"{\n",
"public:\n",
" using A::foo;\n",
"};\n",
"
class Animal {\n",
" public:\n",
" virtual ~Animal() { }\n",
" virtual std::string go(int n_times) = 0;\n",
" };\n",
"
class Animal:\n",
" def go(self, n_times: int) -> str: # overridable (pure virtual)\n",
" pass\n",
" def __init__(self) -> None:\n",
" """Autogenerated default constructor"""\n",
" pass\n",
"
auto pyClassAnimal =\n",
" py::class_<Animal, Animal_trampoline>\n",
" (m, "Animal", "")\n",
" .def(py::init<>()) // implicit default constructor\n",
" .def("go",\n",
" &Animal::go, py::arg("n_times"))\n",
" ;\n",
"
// helper type to enable overriding virtual methods in python\n",
"class Animal_trampoline : public Animal\n",
"{\n",
"public:\n",
" using Animal::Animal;\n",
"\n",
" std::string go(int n_times) override\n",
" {\n",
" PYBIND11_OVERRIDE_PURE_NAME(\n",
" std::string, // return type\n",
" Animal, // parent class\n",
" "go", // function name (python)\n",
" go, // function name (c++)\n",
" n_times // params\n",
" );\n",
" }\n",
"};\n",
"
class Animal {\n",
" public:\n",
" virtual std::string go(int n_times) = 0;\n",
" virtual std::string name() { return "unknown"; }\n",
" };\n",
"\n",
" class Dog : public Animal {\n",
" public:\n",
" std::string go(int n_times) override {\n",
" std::string result;\n",
" for (int i=0; i<n_times; ++i)\n",
" result += bark() + " ";\n",
" return result;\n",
" }\n",
" virtual std::string bark() { return "woof!"; }\n",
" };\n",
"
class Animal:\n",
" def go(self, n_times: int) -> str: # overridable (pure virtual)\n",
" pass\n",
" def name(self) -> str: # overridable\n",
" pass\n",
" def __init__(self) -> None:\n",
" """Autogenerated default constructor"""\n",
" pass\n",
"\n",
"class Dog(Animal):\n",
" def go(self, n_times: int) -> str: # overridable\n",
" pass\n",
" def bark(self) -> str: # overridable\n",
" pass\n",
" def __init__(self) -> None:\n",
" """Autogenerated default constructor"""\n",
" pass\n",
"
auto pyClassAnimal =\n",
" py::class_<Animal, Animal_trampoline>\n",
" (m, "Animal", "")\n",
" .def(py::init<>()) // implicit default constructor\n",
" .def("go",\n",
" &Animal::go, py::arg("n_times"))\n",
" .def("name",\n",
" &Animal::name)\n",
" ;\n",
"\n",
"\n",
"auto pyClassDog =\n",
" py::class_<Dog, Animal, Dog_trampoline>\n",
" (m, "Dog", "")\n",
" .def(py::init<>()) // implicit default constructor\n",
" .def("go",\n",
" &Dog::go, py::arg("n_times"))\n",
" .def("bark",\n",
" &Dog::bark)\n",
" ;\n",
"
// helper type to enable overriding virtual methods in python\n",
"class Animal_trampoline : public Animal\n",
"{\n",
"public:\n",
" using Animal::Animal;\n",
"\n",
" std::string go(int n_times) override\n",
" {\n",
" PYBIND11_OVERRIDE_PURE_NAME(\n",
" std::string, // return type\n",
" Animal, // parent class\n",
" "go", // function name (python)\n",
" go, // function name (c++)\n",
" n_times // params\n",
" );\n",
" }\n",
" std::string name() override\n",
" {\n",
" PYBIND11_OVERRIDE_NAME(\n",
" std::string, // return type\n",
" Animal, // parent class\n",
" "name", // function name (python)\n",
" name // function name (c++)\n",
" );\n",
" }\n",
"};\n",
"\n",
"\n",
"\n",
"// helper type to enable overriding virtual methods in python\n",
"class Dog_trampoline : public Dog\n",
"{\n",
"public:\n",
" using Dog::Dog;\n",
"\n",
" std::string go(int n_times) override\n",
" {\n",
" PYBIND11_OVERRIDE_NAME(\n",
" std::string, // return type\n",
" Dog, // parent class\n",
" "go", // function name (python)\n",
" go, // function name (c++)\n",
" n_times // params\n",
" );\n",
" }\n",
" std::string bark() override\n",
" {\n",
" PYBIND11_OVERRIDE_NAME(\n",
" std::string, // return type\n",
" Dog, // parent class\n",
" "bark", // function name (python)\n",
" bark // function name (c++)\n",
" );\n",
" }\n",
" std::string name() override\n",
" {\n",
" PYBIND11_OVERRIDE_NAME(\n",
" std::string, // return type\n",
" Dog, // parent class\n",
" "name", // function name (python)\n",
" name // function name (c++)\n",
" );\n",
" }\n",
"};\n",
"
struct IntWrapper\n",
" {\n",
" int value;\n",
" IntWrapper(int v) : value(v) {}\n",
"\n",
" // arithmetic operators\n",
" IntWrapper operator+(IntWrapper b) { return IntWrapper{ value + b.value}; }\n",
" IntWrapper operator-(IntWrapper b) { return IntWrapper{ value - b.value }; }\n",
"\n",
" // Unary minus operator\n",
" IntWrapper operator-() { return IntWrapper{ -value }; }\n",
"\n",
" // Comparison operator\n",
" bool operator<(IntWrapper b) { return value < b.value; }\n",
"\n",
" // Two overload of the += operator\n",
" IntWrapper operator+=(IntWrapper b) { value += b.value; return *this; }\n",
" IntWrapper operator+=(int b) { value += b; return *this; }\n",
"\n",
" // Two overload of the call operator, with different results\n",
" int operator()(IntWrapper b) { return value * b.value + 2; }\n",
" int operator()(int b) { return value * b + 3; }\n",
" };\n",
"
class IntWrapper:\n",
" value: int\n",
" def __init__(self, v: int) -> None:\n",
" pass\n",
"\n",
" # arithmetic operators\n",
" def __add__(self, b: IntWrapper) -> IntWrapper:\n",
" pass\n",
" @overload\n",
" def __sub__(self, b: IntWrapper) -> IntWrapper:\n",
" pass\n",
"\n",
" @overload\n",
" def __neg__(self) -> IntWrapper:\n",
" """ Unary minus operator"""\n",
" pass\n",
"\n",
" def __lt__(self, b: IntWrapper) -> bool:\n",
" """ Comparison operator"""\n",
" pass\n",
"\n",
" # Two overload of the += operator\n",
" @overload\n",
" def __iadd__(self, b: IntWrapper) -> IntWrapper:\n",
" pass\n",
" @overload\n",
" def __iadd__(self, b: int) -> IntWrapper:\n",
" pass\n",
"\n",
" # Two overload of the call operator, with different results\n",
" @overload\n",
" def __call__(self, b: IntWrapper) -> int:\n",
" pass\n",
" @overload\n",
" def __call__(self, b: int) -> int:\n",
" pass\n",
"
auto pyClassIntWrapper =\n",
" py::class_<IntWrapper>\n",
" (m, "IntWrapper", "")\n",
" .def_readwrite("value", &IntWrapper::value, "")\n",
" .def(py::init<int>(),\n",
" py::arg("v"))\n",
" .def("__add__",\n",
" &IntWrapper::operator+, py::arg("b"))\n",
" .def("__sub__",\n",
" py::overload_cast<IntWrapper>(&IntWrapper::operator-), py::arg("b"))\n",
" .def("__neg__",\n",
" [](IntWrapper & self) { return self.operator-(); }, "Unary minus operator")\n",
" .def("__lt__",\n",
" &IntWrapper::operator<,\n",
" py::arg("b"),\n",
" "Comparison operator")\n",
" .def("__iadd__",\n",
" py::overload_cast<IntWrapper>(&IntWrapper::operator+=), py::arg("b"))\n",
" .def("__iadd__",\n",
" py::overload_cast<int>(&IntWrapper::operator+=), py::arg("b"))\n",
" .def("__call__",\n",
" py::overload_cast<IntWrapper>(&IntWrapper::operator()), py::arg("b"))\n",
" .def("__call__",\n",
" py::overload_cast<int>(&IntWrapper::operator()), py::arg("b"))\n",
" ;\n",
"
struct Point\n",
" {\n",
" int x;\n",
" int y;\n",
" auto operator<=>(const Point&) const = default;\n",
" };\n",
"
class Point:\n",
" x: int\n",
" y: int\n",
" def __lt__(self, param_0: Point) -> bool:\n",
" """\n",
" (C++ auto return type)\n",
" """\n",
" pass\n",
" def __le__(self, param_0: Point) -> bool:\n",
" """\n",
" (C++ auto return type)\n",
" """\n",
" pass\n",
" def __eq__(self, param_0: Point) -> bool:\n",
" """\n",
" (C++ auto return type)\n",
" """\n",
" pass\n",
" def __ge__(self, param_0: Point) -> bool:\n",
" """\n",
" (C++ auto return type)\n",
" """\n",
" pass\n",
" def __gt__(self, param_0: Point) -> bool:\n",
" """\n",
" (C++ auto return type)\n",
" """\n",
" pass\n",
" def __init__(self, x: int = int(), y: int = int()) -> None:\n",
" """Auto-generated default constructor with named params"""\n",
" pass\n",
"
auto pyClassPoint =\n",
" py::class_<Point>\n",
" (m, "Point", "")\n",
" .def(py::init<>([](\n",
" int x = int(), int y = int())\n",
" {\n",
" auto r = std::make_unique<Point>();\n",
" r->x = x;\n",
" r->y = y;\n",
" return r;\n",
" })\n",
" , py::arg("x") = int(), py::arg("y") = int()\n",
" )\n",
" .def_readwrite("x", &Point::x, "")\n",
" .def_readwrite("y", &Point::y, "")\n",
" .def("__lt__",\n",
" [](const Point & self, const Point & param_0) -> bool\n",
" {\n",
" auto cmp = [&self](auto&& other) -> bool {\n",
" return self.operator<=>(other) < 0;\n",
" };\n",
"\n",
" return cmp(param_0);\n",
" },\n",
" py::arg("param_0"),\n",
" "\\n(C++ auto return type)")\n",
" .def("__le__",\n",
" [](const Point & self, const Point & param_0) -> bool\n",
" {\n",
" auto cmp = [&self](auto&& other) -> bool {\n",
" return self.operator<=>(other) <= 0;\n",
" };\n",
"\n",
" return cmp(param_0);\n",
" },\n",
" py::arg("param_0"),\n",
" "\\n(C++ auto return type)")\n",
" .def("__eq__",\n",
" [](const Point & self, const Point & param_0) -> bool\n",
" {\n",
" auto cmp = [&self](auto&& other) -> bool {\n",
" return self.operator<=>(other) == 0;\n",
" };\n",
"\n",
" return cmp(param_0);\n",
" },\n",
" py::arg("param_0"),\n",
" "\\n(C++ auto return type)")\n",
" .def("__ge__",\n",
" [](const Point & self, const Point & param_0) -> bool\n",
" {\n",
" auto cmp = [&self](auto&& other) -> bool {\n",
" return self.operator<=>(other) >= 0;\n",
" };\n",
"\n",
" return cmp(param_0);\n",
" },\n",
" py::arg("param_0"),\n",
" "\\n(C++ auto return type)")\n",
" .def("__gt__",\n",
" [](const Point & self, const Point & param_0) -> bool\n",
" {\n",
" auto cmp = [&self](auto&& other) -> bool {\n",
" return self.operator<=>(other) > 0;\n",
" };\n",
"\n",
" return cmp(param_0);\n",
" },\n",
" py::arg("param_0"),\n",
" "\\n(C++ auto return type)")\n",
" ;\n",
"
struct Pet {\n",
" Pet(const std::string &name) : name(name) { }\n",
" std::string name;\n",
"};\n",
"
class Pet:\n",
" def __init__(self, name: str) -> None:\n",
" pass\n",
" name: str\n",
"
auto pyClassPet =\n",
" py::class_<Pet>\n",
" (m, "Pet", py::dynamic_attr(), "")\n",
" .def(py::init<const std::string &>(),\n",
" py::arg("name"))\n",
" .def_readwrite("name", &Pet::name, "")\n",
" ;\n",
"
struct Foo { std::vector<int> values; };\n",
" struct Foo2 { \n",
" Foo foo1 = Foo();\n",
" Foo foo2 = Foo();\n",
" };\n",
"
class Foo:\n",
" """\n",
" (has support for copy.copy)\n",
" """\n",
" values: List[int]\n",
" def __init__(self, values: List[int] = List[int]()) -> None:\n",
" """Auto-generated default constructor with named params"""\n",
" pass\n",
"class Foo2:\n",
" """\n",
" (has support for copy.copy and copy.deepcopy)\n",
" """\n",
" foo1: Foo = Foo()\n",
" foo2: Foo = Foo()\n",
" def __init__(self, foo1: Foo = Foo(), foo2: Foo = Foo()) -> None:\n",
" """Auto-generated default constructor with named params"""\n",
" pass\n",
"
auto pyClassFoo =\n",
" py::class_<Foo>\n",
" (m, "Foo", "\\n(has support for copy.copy)")\n",
" .def(py::init<>([](\n",
" std::vector<int> values = std::vector<int>())\n",
" {\n",
" auto r = std::make_unique<Foo>();\n",
" r->values = values;\n",
" return r;\n",
" })\n",
" , py::arg("values") = std::vector<int>()\n",
" )\n",
" .def_readwrite("values", &Foo::values, "")\n",
" .def("__copy__", [](const Foo &self) {\n",
" return Foo(self);\n",
" }) ;\n",
"\n",
"\n",
"auto pyClassFoo2 =\n",
" py::class_<Foo2>\n",
" (m, "Foo2", "\\n(has support for copy.copy and copy.deepcopy)")\n",
" .def(py::init<>([](\n",
" Foo foo1 = Foo(), Foo foo2 = Foo())\n",
" {\n",
" auto r = std::make_unique<Foo2>();\n",
" r->foo1 = foo1;\n",
" r->foo2 = foo2;\n",
" return r;\n",
" })\n",
" , py::arg("foo1") = Foo(), py::arg("foo2") = Foo()\n",
" )\n",
" .def_readwrite("foo1", &Foo2::foo1, "")\n",
" .def_readwrite("foo2", &Foo2::foo2, "")\n",
" .def("__copy__", [](const Foo2 &self) {\n",
" return Foo2(self);\n",
" })\n",
" .def("__deepcopy__", [](const Foo2 &self, py::dict) {\n",
" return Foo2(self);\n",
" }, py::arg("memo")) ;\n",
"
class MyContainer\n",
"{\n",
"public:\n",
" float operator[](int idx);\n",
"\n",
" // We need to have defined begin(), end(), and size() to make the class iterable\n",
" iterator begin(); // This function is excluded from the bindings (see options.fn_exclude_by_name__regex)\n",
" iterator end(); // This function is excluded from the bindings (see options.fn_exclude_by_name__regex)\n",
" size_t size(); // This function is also published as __len__\n",
"private:\n",
" std::vector<float> values;\n",
"};\n",
"
class MyContainer:\n",
" def __getitem__(self, idx: int) -> float:\n",
" pass\n",
"\n",
" # We need to have defined begin(), end(), and size() to make the class iterable\n",
" def size(self) -> int:\n",
" """ This function is also published as __len__"""\n",
" pass\n",
" def __init__(self) -> None:\n",
" """Autogenerated default constructor"""\n",
" pass\n",
" def __iter__(self) -> Iterator[float]:\n",
" pass\n",
" def __len__(self) -> int:\n",
" pass\n",
"
auto pyClassMyContainer =\n",
" py::class_<MyContainer>\n",
" (m, "MyContainer", "")\n",
" .def(py::init<>()) // implicit default constructor\n",
" .def("__getitem__",\n",
" &MyContainer::operator[], py::arg("idx"))\n",
" .def("size",\n",
" &MyContainer::size, "This function is also published as __len__")\n",
" .def("__iter__", [](const MyContainer &v) { return py::make_iterator(v.begin(), v.end()); }, py::keep_alive<0, 1>())\n",
" .def("__len__", [](const MyContainer &v) { return v.size(); })\n",
" ;\n",
"
struct Foo { int values[4]; };\n",
"
class Foo:\n",
" values: np.ndarray # ndarray[type=int, size=4]\n",
" def __init__(self) -> None:\n",
" """Auto-generated default constructor"""\n",
" pass\n",
"
auto pyClassFoo =\n",
" py::class_<Foo>\n",
" (m, "Foo", "")\n",
" .def(py::init<>()) // implicit default constructor \n",
" .def_property("values",\n",
" [](Foo &self) -> pybind11::array\n",
" {\n",
" auto dtype = pybind11::dtype(pybind11::format_descriptor<int>::format());\n",
" auto base = pybind11::array(dtype, {4}, {sizeof(int)});\n",
" return pybind11::array(dtype, {4}, {sizeof(int)}, self.values, base);\n",
" }, [](Foo& self) {},\n",
" "")\n",
" ;\n",
"
struct Foo\n",
" {\n",
" enum class Choice { A, B };\n",
" int HandleChoice(Choice value = Choice::A) { return 0; }\n",
" };\n",
"
class Foo:\n",
" class Choice(enum.Enum):\n",
" a = enum.auto() # (= 0)\n",
" b = enum.auto() # (= 1)\n",
" def handle_choice(self, value: Foo.Choice = Foo.Choice.a) -> int:\n",
" pass\n",
" def __init__(self) -> None:\n",
" """Auto-generated default constructor"""\n",
" pass\n",
"
auto pyClassFoo =\n",
" py::class_<Foo>\n",
" (m, "Foo", "");\n",
"\n",
"{ // inner classes & enums of Foo\n",
" py::enum_<Foo::Choice>(pyClassFoo, "Choice", py::arithmetic(), "")\n",
" .value("a", Foo::Choice::A, "")\n",
" .value("b", Foo::Choice::B, "");\n",
"} // end of inner classes & enums of Foo\n",
"\n",
"pyClassFoo\n",
" .def(py::init<>()) // implicit default constructor \n",
" .def("handle_choice",\n",
" &Foo::HandleChoice, py::arg("value") = Foo::Choice::A)\n",
" ;\n",
"