Зачем интегрировать C++ и Python
Установка pybind11
1pip install pybind1123# Или через conda4conda install -c conda-forge pybind11
Простые функции
▸C++ код
1// math_bindings.cpp2#include <pybind11/pybind11.h>3#include <cmath>45namespace py = pybind11;67double add(double a, double b) {8 return a + b;9}1011double multiply(double a, double b) {12 return a * b;13}1415PYBIND11_MODULE(math_utils, m) {16 m.doc() = "Math utility module";17 m.def("add", &add, "Add two numbers");18 m.def("multiply", &multiply, "Multiply two numbers");19 m.def("sqrt", [](double x) { return std::sqrt(x); }, "Square root");20}
▸Сборка
1# setup.py2from setuptools import setup3from pybind11.setup_helpers import Pybind11Extension, build_ext45ext_modules = [6 Pybind11Extension(7 "math_utils",8 ["math_bindings.cpp"],9 ),10]1112setup(13 name="math_utils",14 ext_modules=ext_modules,15 cmdclass={"build_ext": build_ext},16)
1pip install -e .
▸Использование в Python
1import math_utils23print(math_utils.add(2, 3)) # 5.04print(math_utils.multiply(4, 5)) # 20.05print(math_utils.sqrt(16)) # 4.0
Классы и наследование
1#include <pybind11/pybind11.h>2#include <string>34namespace py = pybind11;56class Animal {7public:8 Animal(const std::string& name) : name_(name) {}9 virtual ~Animal() = default;10 virtual std::string speak() const { return name_ + " speaks"; }11 std::string name() const { return name_; }12protected:13 std::string name_;14};1516class Dog : public Animal {17public:18 Dog(const std::string& name) : Animal(name) {}19 std::string speak() const override { return name_ + " barks"; }20};2122PYBIND11_MODULE(animal_module, m) {23 py::class_<Animal>(m, "Animal")24 .def(py::init<const std::string&>())25 .def("speak", &Animal::speak)26 .def("name", &Animal::name);2728 py::class_<Dog, Animal>(m, "Dog")29 .def(py::init<const std::string&>());30}
Передача STL-контейнеров
1#include <pybind11/stl.h>23std::vector<int> get_numbers() {4 return {1, 2, 3, 4, 5};5}67std::map<std::string, int> get_scores() {8 return {{"Alice", 95}, {"Bob", 87}};9}1011PYBIND11_MODULE(stl_example, m) {12 m.def("get_numbers", &get_numbers);13 m.def("get_scores", &get_scores);14}
Обработка ошибок
1#include <pybind11/exceptions.h>23void risky_operation() {4 throw py::value_error("Something went wrong");5}67PYBIND11_MODULE(error_example, m) {8 m.def("risky_operation", &risky_operation);9}
1try:2 error_example.risky_operation()3except ValueError as e:4 print(f"Error: {e}")
NumPy интеграция
1#include <pybind11/numpy.h>23py::array_t<double> process_array(py::array_t<double> input) {4 auto buf = input.mutable_unchecked<2>();5 auto result = py::array_t<double>({buf.shape(0), buf.shape(1)});6 auto out = result.mutable_unchecked<2>();78 for (ssize_t i = 0; i < buf.shape(0); ++i) {9 for (ssize_t j = 0; j < buf.shape(1); ++j) {10 out(i, j) = buf(i, j) * 2;11 }12 }13 return result;14}
Заключение
pybind11 позволяет легко создавать Python-расширения на C++. Это идеальный способ ускорить критические участки Python-кода, сохраняя удобство Python API. Интеграция с NumPy делает pybind11 незаменимым для data science проектов.