I am trying to package together an existing Python code and a new C++ 11 code using CMake and pybind 11. I think I am missing something simple to add into CMake scripts, but can't find it anywhere: pybind11 examples have only C++ code and none of Python, other online resources are rather convoluted and not up-to-date -- so I just can't figure out how to package functions in both languages together and make them available via Python's import my_package
down the line... as an example, I have cloned the cmake_example from pybind11 and added a mult function into cmake_example/mult.py
def mult(a, b):
return a * b
how would I make it visible along with add
and subtract
to pass the test below?
import cmake_example as m
assert m.__version__ == '0.0.1'
assert m.add(1, 2) == 3
assert m.subtract(1, 2) == -1
assert m.mult(2, 2) == 4
currently, this test fails..
Thanks!
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 the same package, is the following.
You create two modules.
mymodule
is a public interface, a pure Python module_mymodule
is a private implementation, a complied moduleThen in
mymodule
you import necessary symbols from_mymoudle
(and fallback to pure Python version if necessary).Here's example from yarl package:
quoting.py
_quoting.pyx
Update
Here follows the script. For the sake of reproducibility I'm doing it against original cmake_example.
Now create pure Python modules (inside
cmake_example/cmake_example
).cmake_example/__init__.py
cmake_example/math.py
Now let's modify existing files to turn
cmake_example
module intocmake_example._math
.src/main.cpp
(subtract
removed for brevity)CMakeLists.txt
setup.py
Now we can build it.
In my case it produces
dist/cmake_example-0.0.1-cp27-cp27mu-linux_x86_64.whl
(if C++ compilation fails it'scmake_example-0.0.1-py2-none-any.whl
). Here is what it contents (unzip -l ...
):Once you've cloned the repo, cd to top level directory `cmake_example'
Change ./src/main.cpp to include a "mult" function:
(the rest of the file is the same)
Now make it:
The module for import will be created in the ./build directory. Go to it, then within a python shell your example should work.
For the namespace import, you could do something with
pkgutil
:create the directory structure:
and another parallel structure
and place in
./my_mod/__init__.py
in
./extensions/my_mod/__init__.py
Then append both ./my_mod and ./extensions/my_mod to your $PYTHONPATH, it just might work (it does in my example)