问题
I'm trying to build a small Python extension for a certain instantiation of a templated library, using Boost.Python. This library uses extensively the CGAL library, which integrates fairly well with CMake, that I'm therefore using for my project.
Here's the code for my module (python_export.cpp):
#include <boost/python.hpp>
#include <CGAL/Exact_spherical_kernel_3.h>
#include "Sphere_intersecter.h" // header-only
typedef CGAL::Exact_spherical_kernel_3 SK;
template class Sphere_intersecter<SK>; // explicit for "-fno-implicit-templates"
typedef Sphere_intersecter<SK> SI;
BOOST_PYTHON_MODULE(thickness_diag)
{
using namespace boost::python;
class_<SI>("SphereIntersecter", no_init)
.def("add_sphere", &SI::add_sphere)
;
}
And the CMakeLists.txt:
cmake_minimum_required(VERSION 2.6.2)
project(ThicknessDiag-Python)
# CGAL
find_package(CGAL REQUIRED)
include(${CGAL_USE_FILE})
# Boost
find_package(Boost REQUIRED COMPONENTS python)
find_package(PythonLibs 2.7 REQUIRED)
include_directories(${Boost_INCLUDE_DIRS})
include_directories(${PYTHON_INCLUDE_DIRS})
# Shared library
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-implicit-templates")
set(ThicknessDiag-Python "thickness_diag")
add_library(${ThicknessDiag-Python} SHARED python_export.cpp)
set_target_properties(${ThicknessDiag-Python} PROPERTIES PREFIX "")
target_link_libraries(${ThicknessDiag-Python}
${PYTHON_LIBRARIES} ${Boost_LIBRARIES}
${CGAL_LIBRARIES} ${CGAL_3RD_PARTY_LIBRARIES})
Detailed output of the compile command:
[100%] Building CXX object CMakeFiles/thickness_diag.dir/python_export.cpp.o
/usr/bin/c++ -Dthickness_diag_EXPORTS -DCGAL_USE_MPFR -DCGAL_USE_GMP -frounding-math -fno-implicit-templates -O3 -DNDEBUG -fPIC -isystem /usr/local/include -I/usr/include/python2.7 -o CMakeFiles/thickness_diag.dir/python_export.cpp.o -c /home/jmcomets/ThicknessDiag/tests/python_export.cpp
Linking CXX shared library thickness_diag.so
/usr/bin/c++ -fPIC -frounding-math -fno-implicit-templates -O3 -DNDEBUG -shared -Wl,-soname,thickness_diag.so -o thickness_diag.so CMakeFiles/thickness_diag.dir/python_export.cpp.o -L/usr/local/lib -lmpfr -lgmp /usr/local/lib/libCGAL.so /usr/local/lib/libboost_thread.so -lpthread /usr/local/lib/libboost_system.so -lpython2.7 /usr/local/lib/libboost_python.so /usr/local/lib/libCGAL.so /usr/local/lib/libboost_thread.so -lpthread /usr/local/lib/libboost_system.so -lpython2.7 /usr/local/lib/libboost_python.so -Wl,-rpath,/usr/local/lib
Output of importing the shared library:
$ python -c 'import thickness_diag'
Traceback (most recent call last):
File "<string>", line 1, in <module>
ImportError: ./thickness_diag.so: undefined symbol: _ZN5boost6python9converter6detail15registered_baseIRVK18Sphere_intersecterIN4CGAL18Spherical_kernel_3INS5_9CartesianINS5_4GmpqEEENS5_32Algebraic_kernel_for_spheres_2_3IS8_EEEEEE10convertersE
$ nm thickness_diag.so | grep _ZN5boost6python9converter6detail15registered_baseIRVK18Sphere_intersecterIN4CGAL18Spherical_kernel_3INS5_9CartesianINS5_4GmpqEEENS5_32Algebraic_kernel_for_spheres_2_3IS8_EEEEEE10convertersE
U _ZN5boost6python9converter6detail15registered_baseIRVK18Sphere_intersecterIN4CGAL18Spherical_kernel_3INS5_9CartesianINS5_4GmpqEEENS5_32Algebraic_kernel_for_spheres_2_3IS8_EEEEEE10convertersE
I've been struggling with this for the past two days, any help would be awesome ! :)
EDIT: output of ldd
$ ldd thickness_diag.so
linux-vdso.so.1 => (0x00007fffdfdff000)
libgmp.so.10 => /usr/lib/x86_64-linux-gnu/libgmp.so.10 (0x00007fd91eadf000)
libCGAL.so.10 => /usr/local/lib/libCGAL.so.10 (0x00007fd91e8b4000)
libboost_thread.so.1.55.0 => /usr/local/lib/libboost_thread.so.1.55.0 (0x00007fd91e699000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fd91e47c000)
libboost_system.so.1.55.0 => /usr/local/lib/libboost_system.so.1.55.0 (0x00007fd91e278000)
libpython2.7.so.1.0 => /usr/lib/libpython2.7.so.1.0 (0x00007fd91dd79000)
libboost_python.so.1.55.0 => /usr/local/lib/libboost_python.so.1.55.0 (0x00007fd91db2c000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fd91d829000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fd91d612000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fd91d253000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fd91cf57000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007fd91cd4e000)
/lib64/ld-linux-x86-64.so.2 (0x00007fd91ef85000)
libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007fd91cb37000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fd91c933000)
libutil.so.1 => /lib/x86_64-linux-gnu/libutil.so.1 (0x00007fd91c72f000)
回答1:
Okay I figured it out. Turns out that the option -fno-implicit-templates
was preventing boost from doing its normal template instanciation (which is actually pretty obvious).
I then fell back on an error that I thought was fixed: undefined symbol: _ZN18Sphere_intersecterIN4CGAL18Spherical_kernel_3INS0_9CartesianINS0_4GmpqEEENS0_32Algebraic_kernel_for_spheres_2_3IS3_EEEEEC1ERKS8_ (./thickness_diag.so)
Which, when translated via c++filt, gives: Sphere_intersecter<...> >::Sphere_intersecter(Sphere_intersecter<...> const&)
The copy-constructor, which wasn't implemented (non-copyable class)...
The solution was to remove the add the boost::noncopyable
parameter to boost::python::class_
:
#include <boost/python.hpp>
#include <CGAL/Exact_spherical_kernel_3.h>
#include "Sphere_intersecter.h"
typedef CGAL::Exact_spherical_kernel_3 SK;
template class Sphere_intersecter<SK>;
typedef Sphere_intersecter<SK> SI;
BOOST_PYTHON_MODULE(thickness_diag)
{
using namespace boost::python;
class_<SI, boost::noncopyable>("SphereIntersecter")
.def("add_sphere", &SI::add_sphere)
;
}
回答2:
$man nm
...
"U" The symbol is undefined.
What does that mean? It's not there.
Try ldd
on your so
. This will tell you all the libraries it uses. You then need to make sure all the libraries are on LD_LIBRARY_PATH
来源:https://stackoverflow.com/questions/17806238/undefined-symbol-in-boost-python-module