Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to import a binary module generated by pybind11?

I'm trying to use pybind11 for the first time by following the tutorial documentation.

As the documentation says, I created the following example.cpp file with the following content:

#include <pybind11/pybind11.h>

int add(int i, int j) {
    return i + j;
}

PYBIND11_MODULE(example, m) {
    m.doc() = "pybind11 example plugin"; // optional module docstring

    m.def("add", &add, "A function which adds two numbers");
}

And since I'm on macOS, based on this tutorial, I compiled the example file with the following command: (not sure if this is correct but seems to work)

c++ -O3 -Wall -shared -std=c++11 -undefined dynamic_lookup -I /usr/local/Cellar/pybind11/2.4.3/include example.cpp -o example`python3-config --extension-suffix --includes`

This command generates the example.cpython-37m-darwin.so file in the same directory.

And then I created example.py with the following content:

import example
example.add(1, 2)

But when I run the script with python example.py, it shows the following error:

Traceback (most recent call last):
  File "example.py", line 1, in <module>
    import example
  File "/Users/cuinjune/pybind11/build/example.py", line 2, in <module>
    example.add(1, 2)
AttributeError: 'module' object has no attribute 'add'

What is wrong and how to fix this?


EDIT: Previously, it somehow generated example.pyc file but I don't know how the file was generated and now it just says: ImportError: No module named example.

like image 367
Zack Lee Avatar asked Jan 26 '26 19:01

Zack Lee


1 Answers

This line:

/Users/cuinjune/pybind11/build/example.py

says that there is (or was) another file in your work directory (or perhaps /Users/cuinjune/pybind11/build is in your PYTHONPATH) that is a pure Python file, and unrelated to your built example.cpython-37m-darwin.so. When that example.py was imported, presumably some time in the past, the example.pyc you saw was generated. The .pyc remains fully functional standalone, even when the originating example.py was removed. The .pyc file will have the full directory to the original file hardcoded in it, and thus will continue to refer to that file, even when it is removed.

From your update, now all other example.py, .pyc, .pyo are gone, right?

First make sure that the python interpreter you are running matches the tag that you used to build. For example by running:

python3 -c 'import distutils.sysconfig as ds; print(ds.get_config_var("EXT_SUFFIX"))'

(where I'm assuming you used python3 as the command to start the Python interpreter; if not, then change it to the relevant command).

Second, verify the PYTHONPATH envar to see whether the local directory (either fully spelled out, or .) is in it. If not, add it.

With those two covered, it should work ...

Personally, however, I'd first simplify my life by renaming the module to something more unique (rename both example in the .cpp as well as the target on the CLI).

like image 176
Wim Lavrijsen Avatar answered Jan 29 '26 07:01

Wim Lavrijsen



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!