With the popularity and success of the Python programming language, it has become increasingly important for researchers to be able to make software developments available to the Python eco-system by means of extension packages. To this end, the [Pybind11](https://github.com/pybind/pybind11) library provides a convenient approach to generate Python bindings for (existing) C++ code. In this context, the [sciki-build](https://github.com/scikit-build/scikit-build) project can be used to bridge Python's `setuptools` with [CMake](https://cmake.org/). As a result, CMake's features such as, e.g., choice of build-generators, dependency management or cross-compilation, can easily be exploited from within the installation process of the developed Python extension.
With the rising popularity and success of the Python programming language, it has become increasingly important for computational scientists to be able to make their software available to the Python ecosystem. However, exposing compiled extensions from C/C++ to Python has often been cumbersome, error prone and technically challenging in the past, given the plethora of compilers, libraries and relevant target platforms developers have to deal with.
The present article introduces the combination of two packages that promise to make this daunting task much easier and more stable.
First, the [Pybind11](https://github.com/pybind/pybind11) header-only library provides a convenient approach to generate Python bindings for (existing or newly developed) C++ code.
Second, the [sciki-build](https://github.com/scikit-build/scikit-build) package can be used to bridge Python's `setuptools` with [CMake](https://cmake.org/), leveraging the power of CMake for the build process of the Python extension.
As a result, CMake's features such as, e.g., discovering and linking of numerical libraries, dependency management, choice of build-generators, or even cross-compilation can easily be exploited from within the build process of the Python extension.
One key advantage is that the file 'setup.py' stays minimal and simple, and the aforementioned complexities are handled by CMake.
## Basic Usage
The basic usage of pybind11 in combination with scikit-build will be demonstrated in the following using a 'hello-world' Python extension package that can be accessed [here](sebak/pybind11-hello-world).
The basic usage of pybind11 in combination with scikit-build will be demonstrated in the following using a simple Python extension package that can be accessed [here](sebak/pybind11-hello-world).
## pybind11 hello-world
pybind11 is a header-only library that provides conversion from C++ types to Python. The following C++ file demonstrates its use
pybind11 is a header-only library that provides conversion from C++ types to Python. The following C++ file demonstrates its use in combination with NumPy arrays.
```c++
#include<iostream>
#include<pybind11/pybind11.h>
namespacepy=pybind11;
voidhello(){
std::cout<<"Hello, World!"<<std::endl;
}
PYBIND11_MODULE(_hello,m){
m.doc()="Package to say hi";
m.def("hello",&hello,"Prints \"Hello, World!\"");
}
// paste cumsum once ready
```
In order for this example to be compiled, the pybind11 headers (as any other potential dependency) must be available. pybind11 can be installed in [several ways](https://pybind11.readthedocs.io/en/stable/installing.html) and it also natively support various [build systems](https://pybind11.readthedocs.io/en/stable/compiling.html#compiling). However using scikit-build provides a particularly easy approach which is shown in the following.
In order for this example to be compiled, the pybind11 headers (as any other potential dependency) must be available. pybind11 can be installed in [several ways](https://pybind11.readthedocs.io/en/stable/installing.html), and it natively supports various [build systems](https://pybind11.readthedocs.io/en/stable/compiling.html#compiling).
However using scikit-build provides a particularly easy approach which is shown in the following.
## build with scikit-learn
...
...
@@ -44,8 +38,7 @@ Beside the standard setuptools options, it provides [extra options](https://scik
Build-system dependencies have to be specified via the project's `pyproject.toml` file:
...
...
@@ -62,6 +55,11 @@ requires = [
build-backend = "setuptools.build_meta"
```
With modern Python packaging, it is thus not necessary to manually install scikit-build, but all build-dependencies will be installed in an isolated build-environment. Like this, also dependencies like pybind11 or CMake can be made available with an up-to-date version of `pip`. Please note that the `[global]` feature of the pybind11 requirement, which installs headers and libraries, does not apply to the used Python installation or environment but to the dedicated build environment and can thus be used safely here.
Finally, the Python module can be compiled and installed by using the command `pip install --user .` in the root directory of the project.
With modern Python packaging, it is not necessary to manually install pybind11 and scikit-build, instead all build dependencies will be installed in an isolated build environment by `pip`.
Please note that the '[global]' feature of the pybind11 requirement does not affect the Python installation or environment in use, it is only installed into the dedicated build environment and can thus be used safely here.
Q: Why do we need global here only for pb? Needs clarification.
This is a minimal 'hello-world' example demonstrating the use of the [pybind11](https://github.com/pybind/pybind11) binding library using [scikit-build](https://github.com/scikit-build/scikit-build). This example and examples using different python bindings can be found [here](https://github.com/scikit-build/scikit-build-sample-projects).
This is a minimal NumPy-based example demonstrating the use of the [pybind11](https://github.com/pybind/pybind11) binding library in concert with [scikit-build](https://github.com/scikit-build/scikit-build).