#!/usr/bin/env python # coding: utf-8 # # pybind11: Use C++ libraries # # # [pybind11](https://pybind11.readthedocs.io) lets you write Python extensions using pure C++; no special tool or processing step needed. It's just a header-only library that works just about everywhere. Used by SciPy, PyTorch, and many more libraries. # ## Example # # A Python extension in pybind11 looks like this: # # --- # # ```cpp # #include # # namespace py = pybind11; # # int square(int x) { # return x * x; # } # # PYBIND11_MODULE(somecode, m) { # m.def("square", &square); # } # ``` # # --- # You can use `cppimport` to import it for a quick test, or a build system like scikit-build-core to build. I'm not including a compiler in this environment, so I'm not going to build here - see one of my other classes. This is a minimal `CMakeLists.txt`: # # --- # # ```cmake # cmake_minimium_required(VERSION 3.15...3.26) # project(python_example LANGUAGES CXX) # # set(PYBIND11_FINDPYTHON ON) # find_package(pybind11 CONFIG REQUIRED) # # pybind11_add_module(python_example MODULE src/main.cpp) # # install(TARGETS python_example DESTINATION .) # ``` # # --- # And, your pyproject.toml: # # # --- # # ```toml # [build-system] # requires = ["scikit-build-core", "pybind11"] # build-backend = "scikit_build_core.build" # # [project] # name = "example" # version = "0.0.1" # requires-python = ">=3.8" # ``` # --- # If you want to build and distribute, use [cibuildwheel](https://cibuildwheel.readthedocs.io), which is used by Scikit-Learn, Matplotlib, MyPy, and many more; it can be setup for Linux, macOS, and Windows and all common CPython and PyPy versions in just 13 lines: # # --- # # ```yaml # on: [push, pull_request] # # jobs: # build_wheels: # strategy: # matrix: # os: [ubuntu-latest, windows-latest, macos-latest] # runs-on: ${{ matrix.os }} # # steps: # - uses: actions/checkout@v3 # # - uses: pypa/cibuildwheel@v2.14 # # - uses: actions/upload-artifact@v3 # with: # path: ./wheelhouse/*.whl # ``` # --- # # ## So much more # # Some examples of classes: # # ```python # #include # # using namespace pybind11::literals; # # PYBIND11_MODULE(example, m) { # py::class_(m, "Vector") # .def(py::init()) # .def_property("x", &Vector::getX, &Vector::setX) # .def_property("y", &Vector::getY, &Vector::setY) # .def("mag", &Vector::mag, "I am a mag function") # # .def("unit", [](const Vector& self){return self.unit();}) # # .def("__str__", [](const Vector& self){return py::str("[{}, {}]").format(self.getX(), self.getY());}) # # .def(py::self *= float()) # .def(float() * py::self) # .def(py::self * float()) # } # ``` # You can use lambda functions almost anywhere, and you can ask for `py::object` or the C++ type interchangeably, or cast between them.