HYPER MIKAN BOX
検索
最近の変更
メディアマネージャー
サイトマップ
文書の表示
以前のリビジョン
バックリンク
ログイン
トレース:
この文書は読取専用です。文書のソースを閲覧することは可能ですが、変更はできません。もし変更したい場合は管理者に連絡してください。
====== pybind11を使ってみる ====== 作成日: 2023-08-10 (木) [[https://youtu.be/PXEZhuwq0xA|第6回 pybind11を使ってみる]] プロジェクトレイアウト . └── pybind11-examples/ ├── simple/ │ ├── simple.cpp │ └── Makefile └── fakegfx/ ├── fakegfx.cpp ├── sample.py └── Makefile ===== simple ===== ==== simple.cpp ==== <file cpp> #define _hypot hypot // work-around for Python 3.6 and Mingw-w64 11.0.0 #include <pybind11/pybind11.h> namespace py = pybind11; #include <string_view> #include <format> #include <iostream> namespace s { struct ZeroDivisionError : std::runtime_error { using std::runtime_error::runtime_error; }; void greet(std::string_view who) { std::cout << std::format("Hello, {}!\n", who); } int add(int a, int b) { return a + b; } int sub(int a, int b) { return a - b; } int mul(int a, int b) { return a * b; } int div(int a, int b) { if (b == 0) { throw ZeroDivisionError{"division by zero"}; } return a / b; } } // ns s PYBIND11_MODULE(simple, m) { m.def("greet", &s::greet, "Greet to user with Hello."); m.def("add", &s::add, "Add first and second numbers."); m.def("sub", &s::sub, "Subtract second number from first one."); m.def("mul", &s::mul, "Multiply first and second numbers."); m.def("div", &s::div, "Divide first number by second one."); py::register_exception<s::ZeroDivisionError>(m, "ZeroDivisionError", PyExc_ZeroDivisionError); } </file> ==== Makefile ==== <file Makefile> MODNAME = simple PYBIND11_INCLUDES = $(shell pybind11-config --includes) CXXFLAGS = -Wall -std=c++20 -fPIC ${PYBIND11_INCLUDES} LDFLAGS = -LC:\Python36\libs LDLIBS = -lpython36 all: ${MODNAME}.pyd ${MODNAME}.pyd: ${MODNAME}.o ${CXX} -shared ${CXXFLAGS} -o $@ $< ${LDFLAGS} ${LDLIBS} ${MODNAME}.o: ${MODNAME}.cpp ${CXX} -c ${CXXFLAGS} -o $@ $< </file> ===== fakegfx ===== ==== fakegfx.cpp ==== <file cpp> #define _hypot hypot // work-around for Python 3.6 and Mingw-w64 11.0.0 #include <pybind11/pybind11.h> namespace py = pybind11; #include <iostream> namespace g { class Shape { public: virtual ~Shape() = default; virtual void draw() const = 0; }; class RectangleShape : public Shape { public: void draw() const override { std::cout << "+---------+\n" << "| |\n" << "| |\n" << "+---------+\n"; } }; void draw_shape(Shape const &shape) { shape.draw(); } // trampolines that redirects virtual call back to Python class PyShape : public Shape { public: using Shape::Shape; void draw() const override { PYBIND11_OVERRIDE_PURE( void, // return type Shape, // parent type draw, // method name ); } }; class PyRectangleShape : public RectangleShape { public: using RectangleShape::RectangleShape; void draw() const override { PYBIND11_OVERRIDE(void, RectangleShape, draw); } }; } // namespace g PYBIND11_MODULE(fakegfx, m) { py::class_<g::Shape, g::PyShape>(m, "Shape") .def(py::init()) .def("draw", &g::Shape::draw); py::class_<g::RectangleShape, g::Shape, g::PyRectangleShape>(m, "RectangleShape") .def(py::init()) .def("draw", &g::RectangleShape::draw); m.def("draw_shape", &g::draw_shape); } </file> ==== sample.py ==== <file python> import fakegfx class CircleShape(fakegfx.Shape): def draw(self): print("o") class XRectangleShape(fakegfx.RectangleShape): def draw(self): print("x x x x x x") print("x x") print("x x") print("x x x x x x") </file> ==== Makefile ==== <file Makefile> MODNAME = fakegfx PYBIND11_INCLUDES = $(shell pybind11-config --includes) CXXFLAGS = -Wall -std=c++20 -fPIC ${PYBIND11_INCLUDES} LDFLAGS = -LC:\Python36\libs LDLIBS = -lpython36 all: ${MODNAME}.pyd ${MODNAME}.pyd: ${MODNAME}.o ${CXX} -shared ${CXXFLAGS} -o $@ $< ${LDFLAGS} ${LDLIBS} ${MODNAME}.o: ${MODNAME}.cpp ${CXX} -c ${CXXFLAGS} -o $@ $< </file>
文書の先頭へ