Henricus V.
Henricus V.

Reputation: 948

Python is unable to import library compiled with boost_python

I have the following sample program:

// src/main.cpp
#include <boost/python.hpp>

char const* func()
{
    return "String";
}
BOOST_PYTHON_MODULE(bridge)
{
    boost::python::def("func", func);
}

When built using the following CMakeLists.txt, no compiler errors are given:

project(bridge)
cmake_minimum_required(VERSION 3.5)

set(PROJECT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/src)
set(CMAKE_BINARY_DIR ${CMAKE_SOURCE_DIR}/bin)
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR})
set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR})

set(SOURCE_FILES
    ${PROJECT_SOURCE_DIR}/main.cpp
   )

# Include Python
#set(Python_ADDITIONAL_VERSIONS 3.5)
find_package(PythonLibs)
if (${PYTHONLIBS_FOUND})
    include_directories(${PYTHON_INCLUDE_DIRS})
    link_directories(${PYTHON_LIBRARIES})
endif()

# Include Boost
find_package(Boost 1.61.0 COMPONENTS python REQUIRED)
if (${Boost_FOUND})
    include_directories(${Boost_INCLUDE_DIRS})
    link_directories(${Boost_LIBRARY_DIR})
endif()

# Enable C++ 11
add_compile_options(-std=c++11)
add_compile_options("-lboost_python")

add_library(bridge SHARED ${SOURCE_FILES})
target_link_libraries(bridge ${PYTHON_LIBRARIES})
target_link_libraries(bridge ${Boost_LIBRARIES})

However, importing the shared library (libbridge.so) gives the following error:

/bin$ python
Python 2.7.11+ (default, Apr 17 2016, 14:00:29) 
[GCC 5.3.1 20160413] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import libbridge
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: ./libbridge.so: undefined symbol: _ZN5boost6python6detail11init_moduleER11PyModuleDefPFvvE

I have compiled boost and boost_python without any problem, and other boost libraries are fully functional. What is wrong here?

Edit: In another post a solution was given by making the filename the same as the argument fed into BOOST_PYTHON_MODULE. After these modifications, the following error is now given by import libbridge:

ImportError: ./libbridge.so: invalid ELF header

Exporting the environment variable $LD_LIBRARY_PATH=$BOOST_ROOT/stage/lib does not seem to create a difference.

Upvotes: 2

Views: 1077

Answers (1)

Henricus V.
Henricus V.

Reputation: 948

I have found a solution. The problem is due to Python version mismatch inside Boost. I decided to compile everything in Python 3 and it solves the problem. I proceeded as follows:

  1. I uncommented the following line to the auto-generated user-config.jam located in $BOOST_ROOT/tools/build/example/

    using python : 3.5 : /usr/bin/python3 : /usr/include/python3.5 : /usr/lib;

  2. Boost.Python was built from scratch using the commands (executed in sudo to gain permission to /usr/local)

    $BOOST_ROOT : ./b2 --with-python --clean $BOOST_ROOT : ./b2 --with-python --install

I verified that the libraries are indeed Python 3 using

$BOOST_ROOT : nm -D stage/lib/libboost_python-3.so | grep PyClass_Type

No output should be given. If the library was compiled with Python 2, then U PyClass_Type would show up.

  1. The CMakeLists.txt file in the sample project was slightly modified:

    set(Python_ADDITIONAL_VERSIONS 3.5) // uncommented find_package(Boost 1.61.0 COMPONENTS python3 REQUIRED) // python3 instead of python add_compile_options("-lboost_python") // removed

  2. Now python3 (not python) should be able to link against the compiled libbridge.so library.

Upvotes: 2

Related Questions