0

In Python 3, I am trying to import a shared library compiled in C++. Currently, I have these packages installed on CentOS 7:

  • g++ --version -> g++ (GCC) 4.8.5 20150623 (Red Hat 4.8.5-28)
  • conda list anaconda$ -> Anaconda 3 version 5.2.0 with build channel py36_3

A simple file in C++ greet.cpp is compiled into a shared library greet.so with Boost.Python. I followed a video on youtube Simple Demo of Boost Python of Python calling C++ library but it failed to find Python.h for some reasons. I had to changed a few things in makefile and eventually I compiled all with no errors. However, when I try to import the shared library pygreet.so in Python interpreter as a module: import pygreet, I get this error:

ImportError: /home/.../cpp/code/pygreet.so: undefined symbol: _ZN5boost6python6detail11init_moduleER11PyModuleDefPFvvE

I tried to see what this thing is: nm pygreet.so | less -p "_ZN5boost6python6detail11init_moduleER11PyModuleDefPFvvE" and found these line:

0000000000008916 W _ZN5boost6python3da simpleefIPFSsvEEEvPKcT_
                 U _ZN5boost6python6detail11init_moduleER11PyModuleDefPFvvE

I am rather a beginner at using shared libraries and I really don't know how to proceed. Below, I am showing the files in case someone can see I missed something important.

Thanks.


greet.cpp:

#include <string>
#include <boost/python.hpp>


namespace py = boost::python;


std::string greet() {
    return "hello, world";
}


int square(int number) {
    return number * number;
}


BOOST_PYTHON_MODULE(pygreet)
{
    // Add regular functions to the module.
    py::def("greet", greet);
    py::def("square", square);
}

makefile:

CXX = g++
PYLIBPATH = $(shell python3-config --exec-prefix)/lib
LDFLAGS = -L$(PYLIBPATH)
LFLAGS = $(shell python3-config --libs) -lboost_python
CFLAGS = -Wall -Werror
INCLUDES = $(shell python3-config --includes)

SOURCE = greet.cpp
TARGET = pygreet.so
OBJ = $(SOURCE:.cpp=.o)

default: $(TARGET)
    @echo $(TARGET) compiled!

$(TARGET): $(OBJ)
    $(CXX) $(CFLAGS) $(LDFLAGS) $(LFLAGS) -Wl,-rpath,$(PYLIBPATH) -shared $< -o $@

greet.o: $(SOURCE)
    $(CXX) $(CFLAGS) $(INCLUDES) -fpic -c $< -o $@

clean:
    rm -rf *.so *.o

.PHONY: deafult clean

Edit.

As suggested in comment, I changed the line in makefile:

PYLIBPATH = $(shell python3-config --exec-prefix)/lib
LDFLAGS = -L$(PYLIBPATH)
LFLAGS = $(shell python3-config --libs) -lboost_python

to

PYLIBPATH = $(shell python3-config --exec-prefix)
LDFLAGS = $(shell python3-config --ldflags) -lboost_python

and then

$(CXX) $(CFLAGS) $(LDFLAGS) $(LFLAGS) -Wl,-rpath,$(PYLIBPATH) -shared $< -o $@

to

$(CXX) $(CFLAGS) $(LDFLAGS) -Wl,-rpath,$(LDFLAGS) -shared $< -o $@

but still have the same error.

5
  • Why don't you use python3-config --ldflags to get all flags and libraries needed for linking? Commented Jun 14, 2018 at 10:15
  • Ah. I followed the video I provided link to and failed to realise that I could have checked --help. Then, I would know about it. Thanks for pointing this out. I'll check if it runs ok Commented Jun 14, 2018 at 10:24
  • Just one question. What do you think I should provide for -rpath? The whole string returned by python3-config --ldflags? Commented Jun 14, 2018 at 10:29
  • If an rpath is needed, it should be included in the flags provided by --ldflags. Commented Jun 14, 2018 at 10:36
  • It is not provided there. No matter what I use while compiling the shared file, I get have the same error. Commented Jun 14, 2018 at 10:43

1 Answer 1

1

Boost provides separate libraries for Python 2 and Python 3. If you are using Python 3, you need to link with the Python 3 specific library, otherwise you will get undefined symbol errors at module loading time.

On Ubuntu, the library may be called libboost_python-py35.so. I'm pretty sure (but didn't verify) that different minor versions of the boost.python library are upwards compatible, so you may use libboost_python-py35.so with Python 3.6.

If such library is not present on your system, chances are your distro doesn't ship it, in which case you need to build boost.python from sources.

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

3 Comments

I see. I have installed boost from package manager (yum install boost-devel) and it turns out the boost available in Centos7 is only for Python2 :/. Great. Thanks for clarifying this. At least I know where the problem is.
@Celdor There might be a separate package boost-python3-devel, check it out.
sudo yum list available | grep "boost".*"devel" shows this: boost-devel.i686 1.53.0-27.el7 base. I am guessing 27 refers to Python2.7. There is nothing more than that. As pointed out, I probably have to compile boost from sources.

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.