youtube:python-mixing-005
差分
このページの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 ; | ||
+ | </ | ||