Search code examples
dllshared-librariesroscatkin

Roslaunch cannot open shared object file: No such file or directory


I'm having problems with opening a shared library when using roslaunch.

I have a ROS package with a c++ script containing the line:

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

This shared library resides inside my ROS package. I managed to build the package with catking build, having in my CMakeLists.txt the lines

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} 
)

The problem is when I try to run my executable. Since the library is not in a folder where libraries usually are, I added the path to that folder to LD_LIBRARY_PATH and exported it. However I don't understand why I don't get the error in the title only when I use rosrun while I'm inside the exact folder in which the library is. My issue is that I want to launch that node with a launch file, but using roslaunch I get the error in the title anyway, even if I run it from inside the folder of that library.


Solution

  • I think the most portable way of doing so is to supply dlopen with the full path to the shared library file by using ros::package::getPath("your_package_name") as follows (and not modifying LD_LIBRARY_PATH!). This way you can easily get your package up and running on another computer!

    • Modify your node to load the shared library using the absolute path to the shared library by using the function ros::package::getPath from the ros/package.h header:

      std::string const library_path = ros::package::getPath("your_package") + "/relative/path/to/libyourlib.so";
      auto* handle = ::dlopen(library_path.c_str(), RTLD_LAZY);
      

      This for example would be a minimal working example for a node 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;
      }
      
    • Modify your CMakeLists.txt to include the roslib library which contains the ros::package::getPath function:

      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})