Reputation: 2617
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_3A 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.
Upvotes: 0
Views: 1122
Reputation: 120059
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.
Upvotes: 1