4

I am trying to setup a CMake project that creates python bindings for its c++ functions using pybind11 on Ubuntu.

The directory structure is:

pybind_test
    arithmetic.cpp
    arithmetic.h
    bindings.h
    CMakeLists.txt
    main.cpp
    pybind11 (github repo clone)
        Repo contents (https://github.com/pybind/pybind11)

The CMakeLists.txt file:

cmake_minimum_required(VERSION 3.10)
project(pybind_test)

set(CMAKE_CXX_STANDARD 17)

find_package(PythonLibs REQUIRED)
include_directories(${PYTHON_INCLUDE_DIRS})
include_directories(pybind11/include/pybind11)

add_executable(pybind_test main.cpp arithmetic.cpp)

add_subdirectory(pybind11)
pybind11_add_module(arithmetic arithmetic.cpp)

target_link_libraries(pybind_test ${PYTHON_LIBRARIES})

The repository builds successfully and the file arithmetic.cpython-36m-x86_64-linux-gnu.so is produced. How do I import this shared object file into python?

The documentation in the pybind11 docs has this line

$ c++ -O3 -Wall -shared -std=c++11 -fPIC `python3 -m pybind11 --includes` example.cpp -o example`python3-config --extension-suffix`

but I want to build using CMake and I also don't want to have to specify extra include directories every time I run python to use this module.

How would I import this shared object file into python like a normal python module?

I am using Ubuntu 16.04.

2 Answers 2

7

If you open a terminal, go to the directory where arithmetic.cpython-36m-x86_64-linux-gnu.so is located and run python followed by import arithmetic the module will get imported just like any other module.

Another options is to use the method of

import sys

sys.path.insert(0, 'path/to/directory/where/so-file/is')
import arithmetic

With this method you can use both relative and absolute path.

Sign up to request clarification or add additional context in comments.

2 Comments

This results in: Traceback (most recent call last): File "<stdin>", line 1, in <module> ImportError: No module named arithmetic
Ok I fixed this by making sure the module name in my bindings macro, matches the module name in the CMakeLists.txt file.
1

Besides the solution of setting the path in the Python script that is presented by @super, you have two more generic solutions.

Setting PYTHONPATH

There is an environment variable in Linux (and macOS) called PYTHONPATH. If you add the path that contains your *.so to the PYTHONPATH before you call Python, Python will be able to find your library.

To do this:

export PYTHONPATH="/path/that/contains/your/so":"${PYTHONPATH}"

To apply this 'automatically' for every session you can add this line to ~/.bash_profile or ~/.bashrc (see the same reference). In that case, Python will always be able to find your library.

Copying your to a path already in Python's path

You can also 'install' the library. The usual way to do this is to create a setup.py file. If set up correctly you can build and install your library using

python setup.py build
python setup.py install

(Python will know where to put your library. You can 'customize' a bit with an option like --user to use your home-folder, but this doesn't seems to be of particular interest to you.)

The question remains: How to write setup.py? For your case you can actually call CMake. In fact there exists an example that does exactly that: pybind/cmake_example. You can basically copy-paste from there.

1 Comment

Personally I have included the CMake interface in a Python library that I call from most of my projects.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.