Roslaunch 无法打开共享对象文件:没有这样的文件或目录

问题描述

我在使用 roslaunch 时打开共享库时遇到问题。

我有一个包含以下行的 C++ 脚本的 ROS 包:

handle = dlopen("./rk4.so",RTLD_LAZY);

这个共享库位于我的 ROS 包中。我设法用 catking build 构建了包,在我的 CMakeLists.txt 中有这些行

add_library(RK4 SHARED IMPORTED)
set_target_properties(RK4 PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/src/SharedLibs/rk4.so)

target_link_libraries(simulator_node
  RK4
  ${CMAKE_DL_LIBS}
  ${catkin_LIBRARIES} 
)

问题是当我尝试运行我的可执行文件时。由于库不在库通常所在的文件夹中,我将该文件夹的路径添加LD_LIBRARY_PATH 并将其导出。 但是,我不明白为什么只有当我在库所在的确切文件夹中使用 rosrun 时才会在标题中出现错误。 我的问题是我想使用启动文件启动该节点,但是使用 roslaunch 无论如何我都会在标题中出现错误,即使我从该库的文件夹内运行它。

解决方法

此代码:

handle = dlopen("./rk4.so",RTLD_LAZY);

将成功当且仅当当前目录中有rk4.so。特别是,它会忽略任何 LD_LIBRARY_PATH 设置。

这是按设计工作的。

如果您希望 dlopen 尊重 LD_LIBRARY_PATH,请像这样更改它:

  handle = dlopen("rk4.so",RTLD_LAZY);

更好的方法是进行上述更改通过在应用程序的链接时使用 LD_LIBRARY_PATH 来避免设置 -Wl,-rpath=/dir/where/rk4.so/is/installed

,

我认为这样做的最便携方法是使用 dlopenros::package::getPath("your_package_name") 提供共享库文件的完整路径,如下所示(而不是修改 { {1}}!)。通过这种方式,您可以轻松地在另一台计算机上安装并运行您的程序包!

  • 使用 LD_LIBRARY_PATH 标头中的函数 ros::package::getPath 修改您的节点以使用共享库的绝对路径加载共享库:

    ros/package.h

    例如,这将是节点 std::string const library_path = ros::package::getPath("your_package") + "/relative/path/to/libyourlib.so"; auto* handle = ::dlopen(library_path.c_str(),RTLD_LAZY); 的最小工作示例:

    your_node
  • 修改您的 #include <cstdlib> #include <iostream> #include <string> #include <dlfcn.h> #include <ros/ros.h> #include <ros/package.h> int main (int argc,char** argv) { ros::init(argc,argv,"your_node"); ros::NodeHandle n; std::string const package_path = ros::package::getPath("your_package"); std::string const library_path = package_path + "/src/libyourlib.so"; auto* handle = ::dlopen(library_path.c_str(),RTLD_LAZY); if (!handle) { std::cerr << "Error: could not load shared library!" << std::endl; } else { std::cout << "Library successfully loaded!" << std::endl; } return EXIT_SUCCESS; } 以包含包含 CMakeLists.txt 函数的 roslib

    ros::package::getPath