pybind11
is great and I use it all the time. In most cases I need to work with a cmake
file so I start the project off using the cmake example. This usually involves copying the CMakeExtension
/ Builder
class to my setup.py file and adding pybind11
to my project as a git submodule
. I could do without cmake
in simpler projects as shown in the python_example but I find it difficult to use for more complicated projects.
The purpose of this project is to provide an easy to use interface to generate all the boilerplate for the cmake_example and provide the CMakeExtension
/ Builder
class. It also finds the pybind11
headers without needing to make a git submodule
. I will be using this exclusively from now on for all my C++
wrapping needs and hope it is useful to others as well.
Just run (preferably in a virtualenv
)
pip install pybind11_cmake
You can also clone this repo and run pip install .
.
The package exposes a single script: pybind11_new_project
usage: pybind11_new_project [-h] [-a AUTHOR_NAME] [-e AUTHOR_EMAIL] [-c] [-g] package-name cmake-project-name module-name output-directory positional arguments: package-name - cmake-project-name - module-name - output-directory - optional arguments: -h, --help show this help message and exit -a AUTHOR_NAME, --author_name AUTHOR_NAME Author name for setup.py reasons. (default: '') -e AUTHOR_EMAIL, --author_email AUTHOR_EMAIL Author email for setup.py reasons. (default: '') -c, --cmake_file_only Flag for generating only a CMakeLists.txt file. (default: False) -g, --generate_example_src Generate an example c++ file. (default: False)
A basic example would be to go into the root of your project folder and run:
pybind11_new_project test_package test_project test_module . -g
This will create a CMakeLists.txt
file with the project set at test_project
and a pybind11
module defined as test_module
and a corresponding setup.py
file
set up to use that CMakeLists.txt
file to build your module. Because the -g
flag
is used it will also create a main.cpp
file which contains a basic example of how
to expose a function using pybind11
. At this point you can just python setup.py build
,
python setup.py install
or pip install .
your python package. For the above command
after installation you can run
from test_module import *
print(add(5, 5))
print(subtract(20, 5))
Which should print
5 15
There are three major hacks in this repo that I do not like and could use help with:
- I straight up copied all the cmake config information from the pybind11 repo (this is the
tools
directory) - I run a
python
command inside thepybind11Config.cmake
file to find the headers as installed by thepybind11
python package and set the relevantcmake
variables - For the
find_package
command to work withpybind11
installed fromPyPI
in avirtualenv
, the user has to set the pybind11_DIR variable in theirCMakeLists.txt
. I curently do this by calling a python command and discovering the location of thepybind11_cmake
package where thepybind11Config.cmake
file is. The script generates aCMakeLists.txt
file that already contains this line.
If you’re a cmake
/ setup.py
wizard and want to help kindly open a PR with a solution for any of these issues.
You might need to add the PRIVATE
keyword (e.g. target_link_libraries(open_karto PRIVATE Boost::thread)
)
Normally a pybind11 wrapped C++ object is passed as a unique_ptr
. You can instead expose it as a shared_ptr
by doing something like:
py::class_<ScanMatcherConfig, std::shared_ptr<ScanMatcherConfig>>(m, "ScanMatcherConfig")
.def(py::init<>())
.def_readwrite("coarse_angle_resolution", &ScanMatcherConfig::m_pCoarseAngleResolution);
Note the two template arguments for py::class_
.