The simplest solution has nothing to do with pybind11 as such. What authors usually do when they want to combine pure Python and C / Cython / other native extensions in one package is the following.
You create two modules.
mymodule is an open interface, pure Python module_mymodule is a private implementation, executed module
Then, in mymodule you import the necessary characters from _mymoudle (and, if necessary, back to a clean version of Python).
Here is an example from yarl package:
Update
A script follows here. For the sake of reproducibility, I am doing this against the original cmake_example .
git clone --recursive https://github.com/pybind/cmake_example.git
Now create pure Python modules (inside cmake_example/cmake_example ).
cmake_example/__init__.py
"""Root module of your package"""
cmake_example/math.py
def mul(a, b): """Pure Python-only function""" return a * b def add(a, b): """Fallback function""" return a + b try: from ._math import add except ImportError: pass
Now modify the existing files to turn the cmake_example module into cmake_example._math .
src/main.cpp ( subtract removed for brevity)
#include <pybind11/pybind11.h> int add(int i, int j) { return i + j; } namespace py = pybind11; PYBIND11_MODULE(_math, m) { m.doc() = R"pbdoc( Pybind11 example plugin ----------------------- .. currentmodule:: _math .. autosummary:: :toctree: _generate add )pbdoc"; m.def("add", &add, R"pbdoc( Add two numbers Some other explanation about the add function. )pbdoc"); #ifdef VERSION_INFO m.attr("__version__") = VERSION_INFO; #else m.attr("__version__") = "dev"; #endif }
CMakeLists.txt
cmake_minimum_required(VERSION 2.8.12) project(cmake_example) add_subdirectory(pybind11) pybind11_add_module(_math src/main.cpp)
setup.py
# the above stays intact from subprocess import CalledProcessError kwargs = dict( name='cmake_example', version='0.0.1', author='Dean Moldovan', author_email=' dean0x7d@gmail.com ', description='A test project using pybind11 and CMake', long_description='', ext_modules=[CMakeExtension('cmake_example._math')], cmdclass=dict(build_ext=CMakeBuild), zip_safe=False, packages=['cmake_example'] )
Now we can build it.
python setup.py bdist_wheel
In my case, it produces dist/cmake_example-0.0.1-cp27-cp27mu-linux_x86_64.whl (if C ++ compilation failed cmake_example-0.0.1-py2-none-any.whl ). Here is what this content is ( unzip -l ... ):
Archive: cmake_example-0.0.1-cp27-cp27mu-linux_x86_64.whl Length Date Time Name