1

I want to integrate a simple C++ function into Python using Pybind11. Consider the following simple example of a dummy function:

#include <vector>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>

namespace py = pybind11;

// Dummy function: return a vector of size n, filled with 1
std::vector<int> generate_vector(unsigned int n)
{
    std::vector<int> dummy_vector;
    for(int i = 0; i < n; i++) dummy_vector.push_back(1);
    return dummy_vector;
}

// Generate the python bindings for this C++ function
PYBIND11_PLUGIN(example) {
    py::module m("example", "Generate vector of size n");
    m.def("generate_vector", &generate_vector, "Function generates a vector of size n.");
    return m.ptr();
}

I store this code in a function called example.cpp I use Python 3.5.2 with Anaconda. Following the official documentation, I compile the script follows:

c++ -O3 -shared -std=c++11 -I /Users/SECSCL/anaconda3/include/python3.5m `python-config --cflags --ldflags` example.cpp -o example.so

I do not know exactly what the 'python-config' part stands for, but I know it causes a problem. I have tried three options:

  1. python-config: This results in a clang error, linker command failed
  2. python3-config: Same problem as with python-config
  3. python3.4-config: This actually works and creates an example.so file. But when I try to load it from python3.5, I obtain the error

    Fatal Python error: PyThreadState_Get: no current thread

In summary, my question is: How do I compile my code so that I can load it from python3.5? Or more precisely: what do I have to replace the 'python-config' statement with?

1 Answer 1

1

I was able to get your example going on my macOS Sierra early 2015 MacBook Pro.

I used your example.cxx code without any changes.

Before you compile the module, you have to ensure that the anaconda environment is active, so that the compilation command invokes the correct python-config command.

In my case, this was done with: source ~/miniconda3/bin/activate -- you obviously have to replace miniconda3 with anaconda3.

Now double-check that your compile command will invoke the correct python-config by doing: which python3.5-config -- this should show you that it's using your anaconda3 python3.5-config.

Now you can invoke compilation as follows:

c++ -O3 -shared -std=c++11 -I $HOME/build/pybind11/include \
-I $HOME/miniconda3/include/python3.5m \
`python3.5m-config --cflags --libs` -L $HOME/miniconda3/lib/ \
 example.cpp -o example.so

Note that I had to add the include path to my pybind11 checkout, specified the exact python-config version (3.5m), changed the --ldflags to --libs so that python-config would not add the --stack-size link parameter which will cause errors, and finally that I added an -L for the miniconda3 (anaconda in your case) directory containing the libpython3.5m.dylib

After this, I could do:

$ python
Python 3.5.2 |Continuum Analytics, Inc.| (default, Jul  2 2016, 17:52:12)
[GCC 4.2.1 Compatible Apple LLVM 4.2 (clang-425.0.28)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import example
>>> v = example.generate_vector(64)
>>> print(v)
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]

... which is pretty neat!

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

1 Comment

Thanks! This solves my problem. I had issues with the python - config configuration.

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.