Monday, 9 September 2013

"ImportError: undefined symbol" when importing Boost.Python wrapper built with CMake

"ImportError: undefined symbol" when importing Boost.Python wrapper built
with CMake

I'm developing a Python-to-C++ wrapper using Boost.Python and CMake.
I use the following code in CMakeLists.txt to find the Python libraries
and Boost.Python, and build a Python extension:
find_package (PythonLibs REQUIRED)
include_directories (${PYTHON_INCLUDE_PATH})
find_package (Boost 1.53.0 REQUIRED COMPONENTS python)
include_directories (${Boost_INCLUDE_DIRS})
set (WRAPPER_SRC
wrapper.cpp
# many other files...
exception_translator.hpp)
python_add_module (wrapper ${WRAPPER_SRC})
target_link_libraries (wrapper ${Boost_LIBRARIES})
I composed my CMakeLists.txt inspired in [1] and [2] (that's how I found
out that there is a PYTHON_ADD_MODULE command in CMake, etc.)
The project compiles without any problems under Ubuntu with clang and a
shared object is generated (wrapper.so). However, when I try to import the
wrapper from Python with the statement import wrapper, I get the following
error:
>>> import wrapper
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: ./wrapper.so: undefined symbol:
_Z42TriangularPolar2D_Segment_Edge_is_boundary25TriangularPolar2D_Segment22TriangularPolar2D_Edge
This tells me that a function of my wrapper is undefined, but it's present
in the header file (.hpp) and in the implementation file (.cpp), and the
header file is included from the main file (wrapper.cpp). I see no reason
why this symbol would be undefined.
This error happened, though, after I merged to branches in my Git
repository (I merged io into devel, however, there weren't any big changes
in devel after io branched off from it). The "funny" thing is that
everything worked in both branches before the merge. So, if reset the HEAD
to the parten commit of the merge commit in devel it works; and, if I
checkout io, it works. It only doesn't work from the merge commit onwards.
Of course, I tried diff'ing the commits and even bisect'ing, but the
problem is in the merge commit.
I've tried a couple of things already (without any improvement at all):
Clean the build directory and rebuild. Even rm -rf * under build and
configure with CMake again.
Explicitly tell CMake to link the wrapper with the Python library, i.e.,
replace the line target_link_libraries (wrapper ${Boost_LIBRARIES}) with
target_link_libraries (wrapper ${Boost_LIBRARIES} ${PYTHON_LIBRARIES}) as
suggested in [3] (though it always worked in the past the first way).
Declare the problematic functions as "extern C" code to prevent C++ name
mangling, as suggested in [4].
Since I use the Boost.Python macro BOOST_PYTHON_FUNCTION_OVERLOADS to
support default arguments in some other functions but didn't add a
semicolon at the end of the statement, I tried adding the semicolon (even
though it's not necessary according to the Boost.Python documentation on
default arguments). (This didn't change anything at compilation time, but
it was just a desperate try.)
Do you have any suggestions on what the error is or how to find it?

No comments:

Post a Comment