0
$\begingroup$

Rosanswers logo

Dear all,

I am developing a composable ROS 2 lifecycle node. The node uses another external library in order to execute EtherCAT Master functionalities. I have followed the composition tutorial page:

  1. I created a container process in terminal.
  2. Then, I tried to load the node.

The error I am getting is the following:

Failed to load component: Failed to load library: could not load library loadlibrary error: /home/mobile/dev_ws/install/ether_ros2/lib/libether_ros2_component.so: undefined symbol: _ztvn10ether_ros220ethercatcommunicatore, at /tmp/binarydeb/ros-foxy-rcutils-1.1.3/src/shared_library.c:84

##CMakeLists.txt##

cmake_minimum_required(VERSION  3.5)
project(ether_ros2)

# Default to C++17
if(NOT CMAKE_CXX_STANDARD)
  set(CMAKE_CXX_STANDARD 17)
endif()

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
  add_compile_options(-Wall -Wextra -Wpedantic)
endif()

# find dependencies
find_package(ament_cmake REQUIRED)

#find YAML dependency
find_package(yaml_cpp_vendor REQUIRED)

find_package(rclcpp REQUIRED)
find_package(rclcpp_components REQUIRED)
find_package(rclcpp_lifecycle REQUIRED)
find_package(lifecycle_msgs REQUIRED)
find_package(builtin_interfaces REQUIRED)
find_package(rcutils REQUIRED)
find_package(std_msgs REQUIRED)
find_package(rosidl_default_generators REQUIRED)

 # create ament index resource which references the libraries in the binary dir
 set(node_plugins "")
 rosidl_generate_interfaces(${PROJECT_NAME}
      "msg/PdoIn.msg"
      "msg/PdoInXmc.msg"
      "msg/PdoOut.msg"
      "msg/PdoRaw.msg"
      "msg/ModifyPdoVariables.msg"
       DEPENDENCIES builtin_interfaces std_msgs
 )

set(etherlab_include /opt/etherlab/include)
set(etherlab_lib /opt/etherlab/lib/libethercat.so)

set(SOURCES
      src/ether_ros2_component.cpp
      src/utilities.cpp
      src/ethercat_communicator.cpp
      src/ethercat_network.cpp
      src/ethercat_slave.cpp
      src/pdo_in_publisher.cpp
      src/pdo_out_publisher.cpp
      src/pdo_out_listener.cpp
      src/pdo_out_publisher_timer.cpp)

include_directories(include
                    ${etherlab_include})

add_library(${PROJECT_NAME}_component SHARED
  ${SOURCES})

target_compile_definitions(${PROJECT_NAME}_component
      PRIVATE "COMPOSITION_BUILDING_DLL")
target_link_libraries(${PROJECT_NAME}_component
      ${etherlab_lib})
    
ament_target_dependencies(${PROJECT_NAME}_component
  "rclcpp"
  "rclcpp_components"
  "rclcpp_lifecycle"
  "lifecycle_msgs"
  "rosidl_default_generators"
  "std_msgs"
  "builtin_interfaces"
  "yaml_cpp_vendor"
  "rcutils")

rosidl_target_interfaces(${PROJECT_NAME}_component
          ${PROJECT_NAME} "rosidl_typesupport_cpp")
      
rclcpp_components_register_nodes(${PROJECT_NAME}_component "ether_ros2::EthercatCommunicator")
set(node_plugins "${node_plugins}ether_ros2::EthercatCommunicator;$<TARGET_FILE:ether_ros2_component>\n")
       
install(TARGETS
    ${PROJECT_NAME}_component
    ARCHIVE DESTINATION lib
    LIBRARY DESTINATION lib
    RUNTIME DESTINATION bin)
     
ament_package()

Note that the package has been built successfully. How can I resolve this error ?

Thank you for your help.

Best Regards,

Aris.


Originally posted by Akron on ROS Answers with karma: 3 on 2021-06-27

Post score: 0


Original comments

Comment by gvdhoorn on 2021-06-28:\

Note that the package has been built successfully.

that doesn't really say anything in this case: when building shared libraries, the linker will assume that any symbols it can't directly resolve will be present in the execution context into which the shared library will be loaded.

So even if you did not link any libraries, it's very likely your package will still build successfully.

Comment by Akron on 2021-06-28:
Is there any way to determine which symbols create this runtime error ?

$\endgroup$

1 Answer 1

0
$\begingroup$

Rosanswers logo

That's already in the error:

Failed to load library: could not load library loadlibrary error: /home/mobile/dev_ws/install/ether_ros2/lib/libether_ros2_component.so: undefined symbol: _ztvn10ether_ros220ethercatcommunicatore

_ztvn10ether_ros220ethercatcommunicatore is the mangled version of the symbol.

I'm not sure why, but c++filt (which you'd normally use to demangle symbols) can't process it.

Is libethercat.so perhaps a C library, and did you perhaps forget to extern C the #includes of the accompanying header?


Originally posted by gvdhoorn with karma: 86574 on 2021-06-28

This answer was ACCEPTED on the original site

Post score: 1


Original comments

Comment by Akron on 2021-06-28:
It is indeed a C library. I will check for any missing extern C expressions and I will keep you posted. Thanks for the immediate response!

Comment by Akron on 2021-06-29:
@gvdhoorn it seems that your insight about potential missing extern Cs was right. I had indeed missed some of them. Moreover, even though I had declared a destructor, I forgot to define it. I though I had done it inline, but the brackets {} were missing (newbie mistake). Thank you again!

Comment by gvdhoorn on 2021-06-29:\

I had indeed missed some of them.

is this your own library? Or something 3rd party?

In any case: you don't need to declare every function extern C by itself. Something like this would work for all functions declared in header.h:

extern "C" {
  #include </path/to/header.h>
}

it's not too nice, but if header.h is not under your control -- or you can't change it -- it does provide a way to guard the symbols in header.h against name-mangling.

Comment by Akron on 2021-06-30:
Yes it is a third part library. I did what you proposed with the header files. I didn't declare every function.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.