• Stars
    star
    528
  • Rank 83,941 (Top 2 %)
  • Language
    C++
  • License
    MIT License
  • Created almost 8 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Examples for the usage of "pybind11"

Contents

Introduction

The power of pybind11 is captured by the following citation from pybind11's readme:

pybind11 is a lightweight header-only library that exposes C++ types in Python and vice versa, mainly to create Python bindings of existing C++ code. Its goals and syntax are similar to the excellent Boost.Python library by David Abrahams ...

The main issue with Boost.Python - and the reason for creating such a similar project — is Boost. Boost is an enormously large and complex suite of utility libraries that works with almost every C++ compiler in existence. ... Now that C++11-compatible compilers are widely available, this heavy machinery has become an excessively large and unnecessary dependency.

This repository contains several examples for the usage of pybind11. Even though the online documentation provided by the developers of pybind11 makes the usage of it relatively straightforward, several examples - such as provided here - make pybind11 even easier to use. These examples are meant for you to start quicker with pybind11. They are, however, by no means exhaustive, and do not always provide the optimal choice. Therefore it is highly advisable to think for yourself. Furthermore, contributions with similar simple examples (or by further improving existing examples) are highly welcome. Please file a pull request or an issue on GitHub, or contact me.

To give credit where credit is due:

Note that there are also test cases that double as examples in the pybind11 repository, but these are not very insightful when you are new to pybind11.

Finally, pybind11 is actively used. So one can look in actively maintained libraries for specific solutions. For example:

  • cppmat is a library that provided multidimensional arrays in C++, much like the Eigen library does for one- and two-dimensional arrays. It also provides a pybind11 interface, such that creating a Python module that uses cppmat objects as (return) arguments in the back end functions becomes trivial.

Cloning this repository

The pybind11 module (which is header only!) is included as a submodule of this repository. This requires some attention when cloning this project. There are two options:

  • The simplest option is:

    git clone --recursive https://github.com/tdegeus/pybind11_examples.git

    This will download the submodule up to the version that is used in this project. To update to the latest commit of the submodule itself:

    git submodule update --remote
  • One could also directly download the submodule from the source:

    git clone https://github.com/tdegeus/pybind11_examples.git
    cd pybind11_examples
    git submodule init
    git submodule update

Dependencies

The Eigen library is used in some of the NumPy examples. From these examples it can be observed that through pybind11, Eigen and NumPy are really handshake modules. Almost no code is needed to create the C++/Python interface. Note that most of the simplicity depends on copies being passed, some attention is needed if one wants to pass purely by reference.

Eigen does not need installation because it is also header only. One just needs to download the files and include the headers at compile time.

In general one can download and install Eigen by:

mkdir /path/to/temp/build
cmake /path/to/eigen/download
make install

For macOS one could simply use

brew install eigen

Thereafter compile with

clang++ -I/path/to/eigen/instalation ...

Note that, when properly configured (which is normally the case), pkg-config can be used to keep track of the paths:

clang++ `pkg-config --cflags eigen3` ...

Or one can use CMake (see below).

Compiling strategies

DIY

If you have a simple library you might want to do everything yourself. In this case you compile your C++ source to a shared object which is linked to Python. This boils down to

c++ -O3 -shared -std=gnu++11 -I ./pybind11/include `python3-config --cflags --ldflags --libs` example.cpp -o example.so -fPIC

CMake

Basic usage

pybind11 applications can be compiled very easy using CMake. For simplicity pybind11 is included as a sub-folder of the examples below (in fact using a symbolic link to over many copies), so that we can use a CMakeLists.txt like:

cmake_minimum_required(VERSION 2.8.12)
project(example)

add_subdirectory(pybind11)
pybind11_add_module(example example.cpp)

(whereby this example module consists of a single source file example.cpp). To compile it, use:

cd /path/to/build
cmake /path/to/example/src
make

Using Eigen

When Eigen is 'installed' it can be easily included by adding the following in CMakeLists.txt:

find_package( PkgConfig )
pkg_check_modules( EIGEN3 REQUIRED eigen3 )
include_directories( ${EIGEN3_INCLUDE_DIRS} )

Using the C++14 standard

The C++14 standard can be used by including the following in CMakeLists.txt:

set(CMAKE_CXX_STANDARD 14)

setup.py

A file setup.py can be added to your library. You can then compile and install using

python3 setup.py build
python3 setup.py install

Although writing the setup.py is not hard it is not covered here. One can use some tools included in cppmat, that can be installed with pip (e.g. pip3 install cppmat). Furthermore on can look at the setup.py of for example GooseTensor or several other of my repositories.

Examples

01_py-list_cpp-vector

This example features one function modify that takes a list (read-only), multiplies all entries by two, and returns it as a list of doubles (see example.cpp). From Python this function is contained in a simple module example (see test.py).

The purpose of this example is to show how to make a function accept a list, how to convert this to the standard C++ std::vector, and how to return a new std::vector (or list). Note that the actual operation is not very important, it is the interface that is illustrated.

To compile, either employ CMake, whereby the compilation instructions are read from CMakeLists.txt by subsequently:

cmake .
make

Or, compile directly using:

c++ -O3 -shared -std=gnu++11 -I ./pybind11/include `python3-config --cflags --ldflags --libs` example.cpp -o example.so -fPIC

Run the example by:

python3 test.py

To run with Python 2, simply replace the two occurrences of "python3" above with "python". To modify the CMake instructions find more online.

02_py-nested-list_cpp-nested-vector

Same as the previous example, but with a nested list.

03_numpy-1D_cpp-vector

A function modify that converts the entries from a one-dimensional array to integers, and then multiplies these entries by 10.

The purpose of this example is to show how to make a function accept a one-dimensional NumPy array, how to convert this to the standard C++ std::vector, and how to return a one-dimensional NumPy array. Note that the interface generated using pybind11 is so flexible that it even accepts list inputs on the Python side.

04_numpy-2D_cpp-vector

One function length. This function accepts a 'matrix' in which comprises a list of 2-D position vectors, as rows. The result is again a 'matrix' with for each row the "x" and "y" position, and the length of the 2-D position vector.

05_numpy-2D_cpp-eigen

Two functions det and inv that use the Eigen library.

The purpose of this example is to show how trivial the interaction between C++/Eigen and Python/NumPy is.

To compile using CMake and to run, follow the instructions above (whereby the Eigen headers are included in CMakeLists.txt. To compile directly, additionally the Eigen headers have to be included:

c++ -O3 -shared -std=gnu++11 -I /path/to/eigen -I ./pybind11/include `python3-config --cflags --ldflags --libs` example.cpp -o example.so -fPIC

For example on macOS with homebrew:

c++ -O3 -shared -std=gnu++11 -I /usr/local/Cellar/eigen/3.3.1/include/eigen3 -I ./pybind11/include `python3-config --cflags --ldflags --libs` example.cpp -o example.so -fPIC

06_class-numpy-eigen

A custom CustomVectorXd class with one function mul. This class uses the Eigen library. It also includes a default argument.

Furthermore, this example has a function trans (totally unrelated to the custom CustomVectorXd class). It's purpose is to show how to return a new Eigen::VectorXi (or NumPy-array).

07_cpp-overload-scalar

One overloaded function mul. This function acts 'differently' if it is called with int arguments or double arguments. Notice that the default behavior of pybind11 is quite robust. When calling the function with one int and one double argument, the module will choose the double version of mul (and will cast the int argument to a double).

To compile, make sure that the C++14 standard is used, for example by including -std=c++14 as compiler argument.

08_cpp-overload-eigen

Similar to the previous example, but with Eigen arguments (i.e. NumPy arguments from the Python side).

To compile, make sure that the C++14 standard is used.

09_numpy_cpp-custom-matrix

This example includes a custom matrix class in C++ (in matrix.h). This class is coupled to a NumPy-array using a simple interface (in pybind_matrix.h). Consequently the functions (in example.cpp) do not necessitate any special wrapper code.

See also this discussion of Stack Overflow.

10_enum

This example features a way to interface with an enumerator in C++. In principle the interface is straightforward but warrants a 'trick'. Here a submodule is used to be able to interact with the enumerator in the same way as in C++.

11_class-parent-child

This example contains a classical example where one or more classes are derived from a certain parent or template. This particular example contains two animals, a Dog and a Cat, that are both derived from a generic Animal class. There is a function talk that accepts the generic Animal and thus any of the derived classes.

This particular case requires more involved interface, as is described in the documentation.

12_crtp

This example features a simple CRTP with as 'base' and and a 'derived' class, and its registration to the pybind11 API.

13_static_cast

Sometimes py::overload_cast is not able to resolve your function, for example when the return type cannot be inferred. In that case you can be explicit by static_casting a pointer to your function More information can be found in the documentation.

More Repositories

1

GooseFFT

Micro mechanical computations with an FFT-based method
Python
30
star
2

cppcolormap

Library with colormaps for C++
C++
17
star
3

GooseSLURM

SLURM command line tools and scripts
Python
11
star
4

GooseBib

Some simple command-line tools to clean-up / modify BibTeX files
Python
8
star
5

cppmat

[deprecated in favour of xtensor]
C++
7
star
6

cpppath

Simple file-path module for C++
C++
6
star
7

GooseFEM

Several types of Finite Element simulations in C++ (with a Python interface)
C++
6
star
8

pyxtensor

Now fully covered in xtensor-python
Python
5
star
9

GooseEYE

Geometrical statistics
C++
4
star
10

XDMFWrite_h5py

XDMF meets h5py: Write XDMF files to interpret HDF5 files
Python
3
star
11

HDF5pp

[deprecated in favour of GooseHDF5, HighFive, xtensor-io]
C++
3
star
12

goose-thesis

A custom book class for LaTeX
TeX
3
star
13

GooseMaterial

Material models of solids, to be used for example in FEM programs
C++
3
star
14

texplain

Copy TeX-file and included figures to a separate (flattened) folder
Python
2
star
15

GMatElastic

Linear elastic material model
C++
2
star
16

XDMFWrite_HighFive

XDFM meets HighFive: Write XDFM files to interpret HDF5 files
C++
2
star
17

paraview_examples

Some simple Paraview examples
Python
2
star
18

GooseEPM

Implementation of an Elasto Plastic Model
C++
1
star
19

conda_envfile

Merge conda environment yaml files
Python
1
star
20

pdfcombine

Combine PDF files with Ghostscript
Python
1
star
21

enstat

Compute the running ensemble average / histogram
Python
1
star
22

GMatElastoPlasticFiniteStrainSimo

Simo elasto-plastic model
C++
1
star
23

GooseHDF5

Simple command-line tools (and Python library) to inspect HDF5 files (wraps around h5py)
Python
1
star
24

QPot

Library to keep track of a sequential potential energy landscape
C++
1
star