编译生成动态链接库后,调用时出现:
# lichunhong @ lichunhong-ThinkPad-T470p in ~/Documents/src/effective_robotics_programming_with_ros-master/catkin_ws on git:lichunhong/dev x [18:54:05] C:127
$ rosrun path_plan PathPlanSimulation
/home/lichunhong/Documents/src/effective_robotics_programming_with_ros-master/catkin_ws/devel/lib/path_plan/PathPlanSimulation:
symbol lookup error: /home/lichunhong/Documents/src/effective_robotics_programming_with_ros-master/catkin_ws/src/pathPlan/lib/libpathplan.so:
undefined symbol: _ZN12ninebot_algo10AprAlgoLog9instance_E
即 symbol lookup error: libpathplan.so: undefined symbol: _ZN12ninebot_algo10AprAlgoLog9instance_E
出现这种问题时,往往是链接时出现了问题,下面分3步解决
(1)使用file 命令查看 so库的架构,看看是否与平台一致
可以看到,当前so库架构为x86-64,可以在GNU/Linux平台下使用。平台与架构一致
# lichunhong @ lichunhong-ThinkPad-T470p in ~/Documents/src/motion_planner/bin on git:dev x [18:47:54]
$ file libpathplan.so
libpathplan.so: ELF 64-bit LSB shared object, x86-64, version 1 (GNU/Linux), dynamically linked,
BuildID[sha1]=32ae641e73c547376df20ca94746fbf5507de415, not stripped
接下来,需要定位一下 undefined symbol的具体信息
(2)通过 ldd -r xxx.so 命令查看so库链接状态和错误信息
ldd命令,可以查看对应的可执行文件或库文件依赖哪些库,但可执行文件或库文件要求与操作系统的编译器类型相同,即电脑是X86的GCC编译器,那么无法通过ldd命令查看ARM交叉编译器编译出来的可执行文件或库文件。
如果想在Ubuntu等Linux宿主机上查看ARM交叉编译好的可执行程序和库文件的相关依赖关系,可以通过以下命令:
readelf -d xxx.so | grep NEEDED
# lichunhong @ lichunhong-ThinkPad-T470p in ~/Documents/src/effective_robotics_programming_with_ros-master/catkin_ws/src/pathPlan/lib on git:lichunhong/dev x [18:57:19]
$ ldd -r libpathplan.so
linux-vdso.so.1 => (0x00007ffec1bd8000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f186cc0a000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f186c901000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f186c6eb000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f186c321000)
/lib64/ld-linux-x86-64.so.2 (0x00007f186d27a000)
undefined symbol: pthread_create (./libpathplan.so)
undefined symbol: _ZN12ninebot_algo10AprAlgoLog9instance_E (./libpathplan.so)
undefined symbol: _ZN2cv3maxERKNS_3MatES2_ (./libpathplan.so)
undefined symbol: _ZN12ninebot_algo10AprAlgoLog8WriteLogE10LEVEL_TYPEPKcS3_z (./libpathplan.so)
undefined symbol: _ZN2cv6dilateERKNS_11_InputArrayERKNS_12_OutputArrayES2_NS_6Point_IiEEiiRKNS_7Scalar_IdEE (./libpathplan.so)
undefined symbol: _ZN2cvgtERKNS_3MatEd (./libpathplan.so)
undefined symbol: _ZN2cv8fastFreeEPv (./libpathplan.so)
undefined symbol: _ZN2cv3Mat5setToERKNS_11_InputArrayES3_ (./libpathplan.so)
undefined symbol: _ZN12ninebot_algo10AprAlgoLog9instance_E (./libpathplan.so)
可以看到有好多 undefined symbol ,其中就有提到的 _ZN12ninebot_algo10AprAlgoLog9instance_E 错误
(3) 使用 c++filt symbol 定位错误在那个C++文件中
从上面的undefined symbol中,通过cc++filt
,可以定位到大多是opencv的问题
# lichunhong @ lichunhong-ThinkPad-T470p in ~/Documents/src/effective_robotics_programming_with_ros-master/catkin_ws/src/pathPlan/lib on git:lichunhong/dev x [19:04:26] C:1
$ c++filt _ZN2cv7waitKeyEi
cv::waitKey(int)
# lichunhong @ lichunhong-ThinkPad-T470p in ~/Documents/src/effective_robotics_programming_with_ros-master/catkin_ws/src/pathPlan/lib on git:lichunhong/dev x [19:04:31]
$ c++filt _ZN2cv3maxERKNS_3MatES2_
cv::max(cv::Mat const&, cv::Mat const&)
是不是忘记添加opencv的链接库了呢,查看项目的cmakelists,果然没有添加。在cmakelists最后,添加如下代码
target_link_libraries(pathplan
${OpenCV_LIBS}
)
好的,重新编译生成so库,使用 ldd 命令查看是否还有 undefined symbol
$ ldd -r libpathplan.so
undefined symbol: _ZN12ninebot_algo10AprAlgoLog9instance_E (./libpathplan.so)
嗯,只剩一个了,继续
# lichunhong @ lichunhong-ThinkPad-T470p in ~/Documents/src/motion_planner/bin on git:dev x [19:11:52]
$ c++filt _ZN12ninebot_algo10AprAlgoLog9instance_E
ninebot_algo::AprAlgoLog::instance_
原来是log文件错误?查看cmakelists ,在add_library中漏掉了log文件依赖,加上
${PROJECT_SOURCE_DIR}/third_party/ninebot_log/ninebot_log.cpp
add_library{} 整体如下:
add_library(pathplan
SHARED
${AprMotionPlanner_src}
${DWA_SRC}
${THETA_STAR_SRC}
${PROJECT_SOURCE_DIR}/third_party/ninebot_log/ninebot_log.cpp
)
这次生成的so库可以运行了。