youtube:python-mixing-006
pybind11を使ってみる
作成日: 2023-08-10 (木)
プロジェクトレイアウト
. └── pybind11-examples/ ├── simple/ │ ├── simple.cpp │ └── Makefile └── fakegfx/ ├── fakegfx.cpp ├── sample.py └── Makefile
simple
simple.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);
}
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 $@ $<
fakegfx
fakegfx.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);
}
sample.py
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")
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 $@ $<
youtube/python-mixing-006.txt · 最終更新: 2024/02/28 18:26 by freemikan