差分
このページの2つのバージョン間の差分を表示します。
| 両方とも前のリビジョン前のリビジョン | |||
| youtube:python-mixing-005 [2024/02/28 18:26] – 削除 - 外部編集 (不明な日付) 127.0.0.1 | youtube:python-mixing-005 [2024/02/28 18:26] (現在) – ↷ toybox:python-mixing-005 から youtube:python-mixing-005 へページを移動しました。 freemikan | ||
|---|---|---|---|
| 行 1: | 行 1: | ||
| + | ====== Boost.Pythonを使ってみる ====== | ||
| + | |||
| + | 作成日: 2023-08-08 (火) | ||
| + | |||
| + | [[https:// | ||
| + | |||
| + | プロジェクトレイアウト | ||
| + | . | ||
| + | └── extending-demos/ | ||
| + | ├── Jamroot | ||
| + | ├── simple/ | ||
| + | │ | ||
| + | │ | ||
| + | │ | ||
| + | ├── point/ | ||
| + | │ | ||
| + | │ | ||
| + | │ | ||
| + | ├── pypoint/ | ||
| + | │ | ||
| + | │ | ||
| + | │ | ||
| + | └── fakegfx/ | ||
| + | ├── Jamfile | ||
| + | ├── fakegfx.h | ||
| + | ├── fakegfx.cpp | ||
| + | └── test_fakegfx.py | ||
| + | ===== Jamroot ===== | ||
| + | |||
| + | <file jam> | ||
| + | import python ; | ||
| + | |||
| + | lib boost_python3 ; | ||
| + | |||
| + | project | ||
| + | : requirements | ||
| + | < | ||
| + | ; | ||
| + | |||
| + | build-project simple ; | ||
| + | build-project point ; | ||
| + | build-project pypoint ; | ||
| + | build-project fakegfx ; | ||
| + | </ | ||
| + | |||
| + | ===== プロジェクト simple ===== | ||
| + | |||
| + | ==== simple.cpp ==== | ||
| + | |||
| + | <file cpp> | ||
| + | #include < | ||
| + | #include < | ||
| + | #include < | ||
| + | |||
| + | namespace { | ||
| + | void println(std:: | ||
| + | std::cout << s << ' | ||
| + | } | ||
| + | |||
| + | std::string to_upper(std:: | ||
| + | return boost:: | ||
| + | } | ||
| + | } // ns anon | ||
| + | |||
| + | BOOST_PYTHON_MODULE(simple) { | ||
| + | namespace python = boost:: | ||
| + | python:: | ||
| + | python:: | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | ==== test_simple.py ==== | ||
| + | |||
| + | <file python> | ||
| + | import simple | ||
| + | |||
| + | simple.println(" | ||
| + | |||
| + | u = simple.to_upper(" | ||
| + | simple.println(u) | ||
| + | </ | ||
| + | |||
| + | ==== Jamfile ==== | ||
| + | |||
| + | <file jam> | ||
| + | project simple | ||
| + | : requirements | ||
| + | < | ||
| + | ; | ||
| + | |||
| + | python-extension simple : simple.cpp ; | ||
| + | </ | ||
| + | |||
| + | ===== プロジェクト point ===== | ||
| + | |||
| + | ==== point.cpp ==== | ||
| + | |||
| + | <file cpp> | ||
| + | #include < | ||
| + | |||
| + | namespace { | ||
| + | struct Point { | ||
| + | double x = 0.0; | ||
| + | double y = 0.0; | ||
| + | |||
| + | Point() = default; | ||
| + | Point(double x, double y) : x{x}, y{y} {} | ||
| + | }; | ||
| + | | ||
| + | void translate(Point &pt, double tx, double ty) { | ||
| + | pt.x += tx; | ||
| + | pt.y += ty; | ||
| + | } | ||
| + | } | ||
| + | |||
| + | BOOST_PYTHON_MODULE(point) { | ||
| + | using namespace boost:: | ||
| + | | ||
| + | class_< | ||
| + | .def(init< | ||
| + | .def(" | ||
| + | .def_readwrite(" | ||
| + | .def_readwrite(" | ||
| + | | ||
| + | def(" | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | ==== test_point.py ==== | ||
| + | |||
| + | <file python> | ||
| + | import point | ||
| + | |||
| + | pt = point.Point() | ||
| + | print(f" | ||
| + | |||
| + | pt.translate(100, | ||
| + | print(f" | ||
| + | </ | ||
| + | |||
| + | ==== Jamfile ==== | ||
| + | |||
| + | <file jam> | ||
| + | project point | ||
| + | : requirements | ||
| + | < | ||
| + | ; | ||
| + | |||
| + | python-extension point : point.cpp ; | ||
| + | </ | ||
| + | |||
| + | ===== プロジェクト pypoint ===== | ||
| + | |||
| + | ==== pypoint.cpp ==== | ||
| + | |||
| + | <file cpp> | ||
| + | #include < | ||
| + | |||
| + | namespace { | ||
| + | |||
| + | void translate(boost:: | ||
| + | pt.attr(" | ||
| + | pt.attr(" | ||
| + | } | ||
| + | |||
| + | } // ns anon | ||
| + | |||
| + | BOOST_PYTHON_MODULE(pypoint) { | ||
| + | boost:: | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | ==== test_pypoint.py ==== | ||
| + | |||
| + | <file python> | ||
| + | import pypoint | ||
| + | |||
| + | class Point: | ||
| + | def __init__(self, | ||
| + | self.x = x | ||
| + | self.y = y | ||
| + | |||
| + | pt = Point(1, 2) | ||
| + | |||
| + | pypoint.translate(pt, | ||
| + | |||
| + | print(f" | ||
| + | </ | ||
| + | |||
| + | ==== Jamfile ==== | ||
| + | |||
| + | <file jam> | ||
| + | project pypoint | ||
| + | : requirements | ||
| + | < | ||
| + | ; | ||
| + | |||
| + | python-extension pypoint : pypoint.cpp ; | ||
| + | </ | ||
| + | |||
| + | ===== プロジェクト fakegfx ===== | ||
| + | |||
| + | ==== fakegfx.h ==== | ||
| + | |||
| + | <file cpp> | ||
| + | #ifndef FAKEGFX_H | ||
| + | #define FAKEGFX_H | ||
| + | |||
| + | #include < | ||
| + | |||
| + | struct Point { | ||
| + | Point() = default; | ||
| + | Point(double x, double y) : x{x}, y{y} {} | ||
| + | double x, y; | ||
| + | }; | ||
| + | |||
| + | inline void translate(Point &pt, double tx, double ty) { | ||
| + | pt.x += tx; | ||
| + | pt.y += ty; | ||
| + | } | ||
| + | |||
| + | class Shape { | ||
| + | public: | ||
| + | virtual ~Shape() = default; | ||
| + | virtual void draw() const = 0; | ||
| + | }; | ||
| + | |||
| + | class RectangleShape : public Shape { | ||
| + | public: | ||
| + | RectangleShape(Point const & | ||
| + | : position_{position} {} | ||
| + | void draw() const override { | ||
| + | std::cout << " | ||
| + | } | ||
| + | |||
| + | private: | ||
| + | Point position_; | ||
| + | }; | ||
| + | |||
| + | inline void draw_shape(Shape const &shape) { | ||
| + | shape.draw(); | ||
| + | } | ||
| + | |||
| + | inline void draw_rectangle_shape(RectangleShape const &shape) { | ||
| + | shape.draw(); | ||
| + | } | ||
| + | |||
| + | #endif | ||
| + | </ | ||
| + | |||
| + | ==== fakegfx.cpp ==== | ||
| + | |||
| + | <file cpp> | ||
| + | #include " | ||
| + | |||
| + | #include < | ||
| + | #include < | ||
| + | #include < | ||
| + | |||
| + | namespace { | ||
| + | class ShapeWrap : public Shape, public boost:: | ||
| + | public: | ||
| + | void draw() const override { | ||
| + | this-> | ||
| + | } | ||
| + | }; | ||
| + | |||
| + | class RectangleShapeWrap | ||
| + | : public RectangleShape | ||
| + | , public boost:: | ||
| + | public: | ||
| + | RectangleShapeWrap(Point const & | ||
| + | |||
| + | void draw() const override { | ||
| + | if (boost:: | ||
| + | draw(); | ||
| + | } else { | ||
| + | RectangleShape:: | ||
| + | } | ||
| + | } | ||
| + | | ||
| + | void default_draw() const { | ||
| + | std::cout << BOOST_CURRENT_FUNCTION << std::endl; | ||
| + | RectangleShape:: | ||
| + | } | ||
| + | }; | ||
| + | } // ns anon | ||
| + | |||
| + | BOOST_PYTHON_MODULE(fakegfx) { | ||
| + | using namespace boost:: | ||
| + | |||
| + | class_< | ||
| + | .def(init< | ||
| + | .def(" | ||
| + | .def_readwrite(" | ||
| + | .def_readwrite(" | ||
| + | |||
| + | class_< | ||
| + | .def(" | ||
| + | |||
| + | class_< | ||
| + | .def(" | ||
| + | // drawの呼び出しを、関数2に転送する | ||
| + | // 関数2のシグネチャが関数1と一致することを保証させる | ||
| + | // 関数1の指定はそのためだけに必要となる | ||
| + | |||
| + | def(" | ||
| + | def(" | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | ==== test_fakegfx.py ==== | ||
| + | |||
| + | <file python> | ||
| + | import fakegfx | ||
| + | |||
| + | # some points | ||
| + | pt = fakegfx.Point(1, | ||
| + | print(f" | ||
| + | |||
| + | pt.translate(-100, | ||
| + | print(f" | ||
| + | |||
| + | pt2 = fakegfx.Point() | ||
| + | print(f" | ||
| + | |||
| + | # circle shape | ||
| + | # derived from C++ shape class | ||
| + | # Shape <- CircleShape | ||
| + | class CircleShape(fakegfx.Shape): | ||
| + | def draw(self): | ||
| + | # | ||
| + | print(" | ||
| + | |||
| + | circle = CircleShape() | ||
| + | |||
| + | # rectangle shape | ||
| + | # defined in C++ code | ||
| + | rectangle = fakegfx.RectangleShape(pt) | ||
| + | |||
| + | # square shape | ||
| + | # derived from C++ rectangle shape class | ||
| + | # Shape <- RectangleShape <- SquareSahpe | ||
| + | class SquareShape(fakegfx.RectangleShape): | ||
| + | def __init__(self): | ||
| + | super().__init__(pt) | ||
| + | | ||
| + | def draw(self): | ||
| + | fakegfx.RectangleShape.draw(self) # test non-cyclic | ||
| + | print(" | ||
| + | |||
| + | |||
| + | square = SquareShape() | ||
| + | |||
| + | print("# | ||
| + | fakegfx.draw_shape(circle) | ||
| + | print("# | ||
| + | fakegfx.draw_shape(rectangle) | ||
| + | print("# | ||
| + | fakegfx.draw_shape(square) | ||
| + | |||
| + | print(" | ||
| + | circle.draw() | ||
| + | print(" | ||
| + | rectangle.draw() | ||
| + | print(" | ||
| + | square.draw() | ||
| + | </ | ||
| + | |||
| + | ==== Jamfile ==== | ||
| + | |||
| + | <file jam> | ||
| + | project extending | ||
| + | : requirements | ||
| + | < | ||
| + | ; | ||
| + | |||
| + | python-extension fakegfx : fakegfx.cpp ; | ||
| + | </ | ||
