From 6a18bbfa1fe80bc5474b19bbda50991f1ac9546b Mon Sep 17 00:00:00 2001 From: Stefan Fabian Date: Tue, 20 Aug 2024 17:04:29 +0200 Subject: [PATCH] Generate typesupport getter declarations for actions, messages and services. (#778) Signed-off-by: Stefan Fabian --- ...dl_generator_cpp_generate_interfaces.cmake | 12 +++ .../resource/action__type_support.hpp.em | 66 ++++++++++++++++ rosidl_generator_cpp/resource/idl.hpp.em | 1 + .../resource/idl__type_support.hpp.em | 77 +++++++++++++++++++ .../resource/msg__type_support.hpp.em | 24 ++++++ ...l_generator_cpp__visibility_control.hpp.in | 42 ++++++++++ .../resource/srv__type_support.hpp.em | 39 ++++++++++ .../rosidl_generator_cpp/__init__.py | 1 + 8 files changed, 262 insertions(+) create mode 100644 rosidl_generator_cpp/resource/action__type_support.hpp.em create mode 100644 rosidl_generator_cpp/resource/idl__type_support.hpp.em create mode 100644 rosidl_generator_cpp/resource/msg__type_support.hpp.em create mode 100644 rosidl_generator_cpp/resource/rosidl_generator_cpp__visibility_control.hpp.in create mode 100644 rosidl_generator_cpp/resource/srv__type_support.hpp.em diff --git a/rosidl_generator_cpp/cmake/rosidl_generator_cpp_generate_interfaces.cmake b/rosidl_generator_cpp/cmake/rosidl_generator_cpp_generate_interfaces.cmake index 9e8f9f546..0240e5b13 100644 --- a/rosidl_generator_cpp/cmake/rosidl_generator_cpp_generate_interfaces.cmake +++ b/rosidl_generator_cpp/cmake/rosidl_generator_cpp_generate_interfaces.cmake @@ -28,6 +28,7 @@ foreach(_abs_idl_file ${rosidl_generate_interfaces_ABS_IDL_FILES}) "${_output_path}/${_parent_folder}/detail/${_header_name}__builder.hpp" "${_output_path}/${_parent_folder}/detail/${_header_name}__struct.hpp" "${_output_path}/${_parent_folder}/detail/${_header_name}__traits.hpp" + "${_output_path}/${_parent_folder}/detail/${_header_name}__type_support.hpp" ) endforeach() @@ -89,6 +90,17 @@ add_custom_command( VERBATIM ) +# generate header to switch between export and import for a specific package +set(_visibility_control_file + "${_output_path}/msg/rosidl_generator_cpp__visibility_control.hpp") +string(TOUPPER "${PROJECT_NAME}" PROJECT_NAME_UPPER) +configure_file( + "${rosidl_generator_cpp_TEMPLATE_DIR}/rosidl_generator_cpp__visibility_control.hpp.in" + "${_visibility_control_file}" + @ONLY +) +list(APPEND _generated_headers "${_visibility_control_file}") + # INTERFACE libraries can't have file-level dependencies in CMake, # so make a custom target depending on the generated files # TODO(sloretz) make this target name less generic than "__cpp" when other diff --git a/rosidl_generator_cpp/resource/action__type_support.hpp.em b/rosidl_generator_cpp/resource/action__type_support.hpp.em new file mode 100644 index 000000000..471cf2c3d --- /dev/null +++ b/rosidl_generator_cpp/resource/action__type_support.hpp.em @@ -0,0 +1,66 @@ +@# Included from rosidl_generator_cpp/resource/action__type_support.hpp.em +@{header_file = 'rosidl_typesupport_cpp/action_type_support.hpp'}@ +@[if header_file in include_directives]@ +// already included above +// @ +@[else]@ +@{include_directives.add(header_file)}@ +@[end if]@ +#include "@(header_file)" + +#ifdef __cplusplus +extern "C" +{ +#endif +// Forward declare the get type support functions for this type. +ROSIDL_GENERATOR_CPP_PUBLIC_@(package_name) +const rosidl_action_type_support_t * + ROSIDL_TYPESUPPORT_INTERFACE__ACTION_SYMBOL_NAME( + rosidl_typesupport_cpp, + @(',\n '.join(action.namespaced_type.namespaced_name())) +)(); +#ifdef __cplusplus +} +#endif + +@{ +TEMPLATE( + 'msg__type_support.hpp.em', + package_name=package_name, message=action.goal, + include_directives=include_directives) +}@ + +@{ +TEMPLATE( + 'msg__type_support.hpp.em', + package_name=package_name, message=action.result, + include_directives=include_directives) +}@ + +@{ +TEMPLATE( + 'msg__type_support.hpp.em', + package_name=package_name, message=action.feedback, + include_directives=include_directives) +}@ + +@{ +TEMPLATE( + 'srv__type_support.hpp.em', + package_name=package_name, service=action.send_goal_service, + include_directives=include_directives) +}@ + +@{ +TEMPLATE( + 'srv__type_support.hpp.em', + package_name=package_name, service=action.get_result_service, + include_directives=include_directives) +}@ + +@{ +TEMPLATE( + 'msg__type_support.hpp.em', + package_name=package_name, message=action.feedback_message, + include_directives=include_directives) +}@ diff --git a/rosidl_generator_cpp/resource/idl.hpp.em b/rosidl_generator_cpp/resource/idl.hpp.em index acb84945e..f239baf9b 100644 --- a/rosidl_generator_cpp/resource/idl.hpp.em +++ b/rosidl_generator_cpp/resource/idl.hpp.em @@ -25,5 +25,6 @@ include_base = '/'.join(include_parts_detail) #include "@(include_base)__struct.hpp" #include "@(include_base)__builder.hpp" #include "@(include_base)__traits.hpp" +#include "@(include_base)__type_support.hpp" #endif // @(header_guard_variable) diff --git a/rosidl_generator_cpp/resource/idl__type_support.hpp.em b/rosidl_generator_cpp/resource/idl__type_support.hpp.em new file mode 100644 index 000000000..9378218d2 --- /dev/null +++ b/rosidl_generator_cpp/resource/idl__type_support.hpp.em @@ -0,0 +1,77 @@ +// generated from rosidl_generator_cpp/resource/idl__type_support.hpp.em +// with input from @(package_name):@(interface_path) +// generated code does not contain a copyright notice +@ +@####################################################################### +@# EmPy template for generating __struct.h files +@# +@# Context: +@# - package_name (string) +@# - interface_path (Path relative to the directory named after the package) +@# - content (IdlContent, list of elements, e.g. Messages or Services) +@####################################################################### +@{ +from rosidl_cmake import convert_camel_case_to_lower_case_underscore +include_parts = [package_name] + list(interface_path.parents[0].parts) + [ + 'detail', convert_camel_case_to_lower_case_underscore(interface_path.stem)] +header_guard_variable = '__'.join([x.upper() for x in include_parts]) + \ + '__TYPE_SUPPORT_HPP_' + +include_directives = set() +}@ + +#ifndef @(header_guard_variable) +#define @(header_guard_variable) + +#include "rosidl_typesupport_interface/macros.h" + +#include "@(package_name)/msg/rosidl_generator_cpp__visibility_control.hpp" + +@####################################################################### +@# Handle message +@####################################################################### +@{ +from rosidl_parser.definition import Message +}@ +@[for message in content.get_elements_of_type(Message)]@ +@{ +TEMPLATE( + 'msg__type_support.hpp.em', + package_name=package_name, message=message, + include_directives=include_directives) +}@ + +@[end for]@ +@ +@####################################################################### +@# Handle service +@####################################################################### +@{ +from rosidl_parser.definition import Service +}@ +@[for service in content.get_elements_of_type(Service)]@ +@{ +TEMPLATE( + 'srv__type_support.hpp.em', + package_name=package_name, service=service, + include_directives=include_directives) +}@ + +@[end for]@ +@ +@####################################################################### +@# Handle action +@####################################################################### +@{ +from rosidl_parser.definition import Action +}@ +@[for action in content.get_elements_of_type(Action)]@ +@{ +TEMPLATE( + 'action__type_support.hpp.em', + package_name=package_name, action=action, + include_directives=include_directives) +}@ + +@[end for]@ +#endif // @(header_guard_variable) diff --git a/rosidl_generator_cpp/resource/msg__type_support.hpp.em b/rosidl_generator_cpp/resource/msg__type_support.hpp.em new file mode 100644 index 000000000..53d8f5fe2 --- /dev/null +++ b/rosidl_generator_cpp/resource/msg__type_support.hpp.em @@ -0,0 +1,24 @@ +@# Included from rosidl_generator_cpp/resource/msg__type_support.hpp.em +@{header_file = 'rosidl_typesupport_cpp/message_type_support.hpp'}@ +@[if header_file in include_directives]@ +// already included above +// @ +@[else]@ +@{include_directives.add(header_file)}@ +@[end if]@ +#include "@(header_file)" + +#ifdef __cplusplus +extern "C" +{ +#endif +// Forward declare the get type support functions for this type. +ROSIDL_GENERATOR_CPP_PUBLIC_@(package_name) +const rosidl_message_type_support_t * + ROSIDL_TYPESUPPORT_INTERFACE__MESSAGE_SYMBOL_NAME( + rosidl_typesupport_cpp, + @(',\n '.join(message.structure.namespaced_type.namespaced_name())) +)(); +#ifdef __cplusplus +} +#endif diff --git a/rosidl_generator_cpp/resource/rosidl_generator_cpp__visibility_control.hpp.in b/rosidl_generator_cpp/resource/rosidl_generator_cpp__visibility_control.hpp.in new file mode 100644 index 000000000..33f238310 --- /dev/null +++ b/rosidl_generator_cpp/resource/rosidl_generator_cpp__visibility_control.hpp.in @@ -0,0 +1,42 @@ +// generated from rosidl_generator_cpp/resource/rosidl_generator_cpp__visibility_control.hpp.in +// generated code does not contain a copyright notice + +#ifndef @PROJECT_NAME_UPPER@__MSG__ROSIDL_GENERATOR_CPP__VISIBILITY_CONTROL_HPP_ +#define @PROJECT_NAME_UPPER@__MSG__ROSIDL_GENERATOR_CPP__VISIBILITY_CONTROL_HPP_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +// This logic was borrowed (then namespaced) from the examples on the gcc wiki: +// https://gcc.gnu.org/wiki/Visibility + +#if defined _WIN32 || defined __CYGWIN__ + #ifdef __GNUC__ + #define ROSIDL_GENERATOR_CPP_EXPORT_@PROJECT_NAME@ __attribute__ ((dllexport)) + #define ROSIDL_GENERATOR_CPP_IMPORT_@PROJECT_NAME@ __attribute__ ((dllimport)) + #else + #define ROSIDL_GENERATOR_CPP_EXPORT_@PROJECT_NAME@ __declspec(dllexport) + #define ROSIDL_GENERATOR_CPP_IMPORT_@PROJECT_NAME@ __declspec(dllimport) + #endif + #ifdef ROSIDL_GENERATOR_CPP_BUILDING_DLL_@PROJECT_NAME@ + #define ROSIDL_GENERATOR_CPP_PUBLIC_@PROJECT_NAME@ ROSIDL_GENERATOR_CPP_EXPORT_@PROJECT_NAME@ + #else + #define ROSIDL_GENERATOR_CPP_PUBLIC_@PROJECT_NAME@ ROSIDL_GENERATOR_CPP_IMPORT_@PROJECT_NAME@ + #endif +#else + #define ROSIDL_GENERATOR_CPP_EXPORT_@PROJECT_NAME@ __attribute__ ((visibility("default"))) + #define ROSIDL_GENERATOR_CPP_IMPORT_@PROJECT_NAME@ + #if __GNUC__ >= 4 + #define ROSIDL_GENERATOR_CPP_PUBLIC_@PROJECT_NAME@ __attribute__ ((visibility("default"))) + #else + #define ROSIDL_GENERATOR_CPP_PUBLIC_@PROJECT_NAME@ + #endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif // @PROJECT_NAME_UPPER@__MSG__ROSIDL_GENERATOR_CPP__VISIBILITY_CONTROL_HPP_ diff --git a/rosidl_generator_cpp/resource/srv__type_support.hpp.em b/rosidl_generator_cpp/resource/srv__type_support.hpp.em new file mode 100644 index 000000000..904604318 --- /dev/null +++ b/rosidl_generator_cpp/resource/srv__type_support.hpp.em @@ -0,0 +1,39 @@ +@# Included from rosidl_generator_cpp/resource/srv__type_support.hpp.em +@{header_file = 'rosidl_typesupport_cpp/service_type_support.hpp'}@ +@[if header_file in include_directives]@ +// already included above +// @ +@[else]@ +@{include_directives.add(header_file)}@ +@[end if]@ +#include "@(header_file)" + +#ifdef __cplusplus +extern "C" +{ +#endif +// Forward declare the get type support functions for this type. +ROSIDL_GENERATOR_CPP_PUBLIC_@(package_name) +const rosidl_service_type_support_t * + ROSIDL_TYPESUPPORT_INTERFACE__SERVICE_SYMBOL_NAME( + rosidl_typesupport_cpp, + @(',\n '.join(service.namespaced_type.namespaced_name())) +)(); +#ifdef __cplusplus +} +#endif + +@{ +TEMPLATE( + 'msg__type_support.hpp.em', + package_name=package_name, message=service.request_message, + include_directives=include_directives) +}@ + +@{ +TEMPLATE( + 'msg__type_support.hpp.em', + package_name=package_name, message=service.response_message, + include_directives=include_directives) +}@ + diff --git a/rosidl_generator_cpp/rosidl_generator_cpp/__init__.py b/rosidl_generator_cpp/rosidl_generator_cpp/__init__.py index 9fbbf62f0..6960eb387 100644 --- a/rosidl_generator_cpp/rosidl_generator_cpp/__init__.py +++ b/rosidl_generator_cpp/rosidl_generator_cpp/__init__.py @@ -34,6 +34,7 @@ def generate_cpp(generator_arguments_file): 'idl__builder.hpp.em': 'detail/%s__builder.hpp', 'idl__struct.hpp.em': 'detail/%s__struct.hpp', 'idl__traits.hpp.em': 'detail/%s__traits.hpp', + 'idl__type_support.hpp.em': 'detail/%s__type_support.hpp', } return generate_files( generator_arguments_file, mapping,