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

Posted

技术标签:

【中文标题】Roslaunch 无法打开共享对象文件:没有这样的文件或目录【英文标题】:Roslaunch cannot open shared object file: No such file or directory 【发布时间】:2021-06-04 12:43:10 【问题描述】:

我在使用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 无论如何我都会在标题中收到错误,即使我从该库的文件夹中运行它也是如此。

【问题讨论】:

你不能把ros::package::getPath("your_package_name")添加到dlopen中的目录吗? @2b-t 你是什么意思?你能更明确地解释一下吗? (对不起,我是初学者) 我的意思是dlopenfilename 作为第一个参数。使用ros::package::getPackage("your_package_name"),您可以获得包的目录。如果您的 ROS 包如您所述位于您的包目录中,那么您应该能够将其组合到像 handle = dlopen(ros::package::getPackage("your_package_name") + "/rk4.so", RTLD_LAZY); 这样的绝对文件路径。我不确定这是否能解决您的问题,因为我还没有机会对其进行测试。 刚刚对其进行了测试,如果您考虑从 std::stringchar const* 的转换(请参阅下面的答案),它可以工作。 我不建议您修改LD_LIBRARY_PATH,因为它是一个环境变量。相反,请尽量让您的修改保持可移植性。 【参考方案1】:

我认为这样做最便携的方法是使用ros::package::getPath("your_package_name")dlopen提供共享库文件的完整路径,如下所示(而不是修改LD_LIBRARY_PATH!) .这样您就可以轻松地在另一台计算机上启动并运行您的程序包!

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

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 函数:

find_package(catkin REQUIRED COMPONENTS
  roscpp
  roslib
)

include_directories(
  $catkin_INCLUDE_DIRS
)

add_executable(your_node src/your_node.cpp)
target_link_libraries(your_node $catkin_LIBRARIES $CMAKE_DL_LIBS)

【讨论】:

【参考方案2】:

这段代码:

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

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

这是按设计工作的。

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

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

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

【讨论】:

以上是关于Roslaunch 无法打开共享对象文件:没有这样的文件或目录的主要内容,如果未能解决你的问题,请参考以下文章

加载共享库时出错:libgmock.so:无法打开共享对象文件:没有这样的文件或目录

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

加载共享库时出错:libgfortran.so.1:无法打开共享对象文件:没有这样的文件或目录

libcrypto.so.10:无法打开共享对象文件:没有这样的文件或目录

自己的lib,另一台计算机:无法打开共享对象文件:没有这样的文件或目录

clang:加载共享库时出错:libtinfo.so.5:无法打开共享对象文件:没有这样的文件或目录