diff --git a/rosidl_adapter/rosidl_adapter/parser.py b/rosidl_adapter/rosidl_adapter/parser.py index 41ed6bf20..836a3b751 100644 --- a/rosidl_adapter/rosidl_adapter/parser.py +++ b/rosidl_adapter/rosidl_adapter/parser.py @@ -26,6 +26,7 @@ SERVICE_REQUEST_RESPONSE_SEPARATOR = '---' SERVICE_REQUEST_MESSAGE_SUFFIX = '_Request' SERVICE_RESPONSE_MESSAGE_SUFFIX = '_Response' +SERVICE_EVENT_MESSAGE_SUFFIX = '_Event' ACTION_REQUEST_RESPONSE_SEPARATOR = '---' ACTION_GOAL_SUFFIX = '_Goal' diff --git a/rosidl_cmake/cmake/rosidl_generate_interfaces.cmake b/rosidl_cmake/cmake/rosidl_generate_interfaces.cmake index f585d93ee..c0273e66d 100644 --- a/rosidl_cmake/cmake/rosidl_generate_interfaces.cmake +++ b/rosidl_cmake/cmake/rosidl_generate_interfaces.cmake @@ -139,11 +139,25 @@ macro(rosidl_generate_interfaces target) # afterwards all remaining interface files are .idl files list(APPEND _idl_tuples ${_idl_adapter_tuples}) - # to generate action interfaces, we need to depend on "action_msgs" + # Check for any action or service interfaces + # Which have implicit dependencies that need to be found foreach(_tuple ${_interface_tuples}) + # We use the parent directory name to identify if the interface is an action or service string(REGEX REPLACE ".*:([^:]*)$" "\\1" _tuple_file "${_tuple}") get_filename_component(_parent_dir "${_tuple_file}" DIRECTORY) + get_filename_component(_parent_dir ${_parent_dir} NAME) + if("${_parent_dir}" STREQUAL "action") + # Actions depend on the packages service_msgs and action_msgs + find_package(service_msgs QUIET) + if(NOT ${service_msgs_FOUND}) + message(FATAL_ERROR + "Unable to generate action interface for '${_tuple_file}'. " + "In order to generate action interfaces you must add a depend tag " + "for 'service_msgs' in your package.xml.") + endif() + ament_export_dependencies(service_msgs) + list_append_unique(_ARG_DEPENDENCIES "service_msgs") find_package(action_msgs QUIET) if(NOT ${action_msgs_FOUND}) message(FATAL_ERROR @@ -151,9 +165,23 @@ macro(rosidl_generate_interfaces target) "In order to generate action interfaces you must add a depend tag " "for 'action_msgs' in your package.xml.") endif() - list_append_unique(_ARG_DEPENDENCIES "action_msgs") ament_export_dependencies(action_msgs) + list_append_unique(_ARG_DEPENDENCIES "action_msgs") + + # It is safe to break out of the loop since services only depend on service_msgs + # Which has already been found above break() + elseif("${_parent_dir}" STREQUAL "srv") + # Services depend on service_msgs + find_package(service_msgs QUIET) + if(NOT ${service_msgs_FOUND}) + message(FATAL_ERROR + "Unable to generate service interface for '${_tuple_file}'. " + "In order to generate service interfaces you must add a depend tag " + "for 'service_msgs' in your package.xml.") + endif() + ament_export_dependencies(service_msgs) + list_append_unique(_ARG_DEPENDENCIES "service_msgs") endif() endforeach() diff --git a/rosidl_generator_c/cmake/rosidl_generator_c_generate_interfaces.cmake b/rosidl_generator_c/cmake/rosidl_generator_c_generate_interfaces.cmake index b024fe054..11652ea9b 100644 --- a/rosidl_generator_c/cmake/rosidl_generator_c_generate_interfaces.cmake +++ b/rosidl_generator_c/cmake/rosidl_generator_c_generate_interfaces.cmake @@ -34,6 +34,7 @@ foreach(_abs_idl_file ${rosidl_generate_interfaces_ABS_IDL_FILES}) ) list(APPEND _generated_sources "${_output_path}/${_parent_folder}/detail/${_header_name}__functions.c" + "${_output_path}/${_parent_folder}/detail/${_header_name}__type_support.c" ) endforeach() @@ -52,15 +53,18 @@ set(target_dependencies "${rosidl_generator_c_BIN}" ${rosidl_generator_c_GENERATOR_FILES} "${rosidl_generator_c_TEMPLATE_DIR}/action__type_support.h.em" + "${rosidl_generator_c_TEMPLATE_DIR}/action__type_support.c.em" "${rosidl_generator_c_TEMPLATE_DIR}/idl.h.em" "${rosidl_generator_c_TEMPLATE_DIR}/idl__functions.c.em" "${rosidl_generator_c_TEMPLATE_DIR}/idl__functions.h.em" "${rosidl_generator_c_TEMPLATE_DIR}/idl__struct.h.em" + "${rosidl_generator_c_TEMPLATE_DIR}/idl__type_support.c.em" "${rosidl_generator_c_TEMPLATE_DIR}/idl__type_support.h.em" "${rosidl_generator_c_TEMPLATE_DIR}/msg__functions.c.em" "${rosidl_generator_c_TEMPLATE_DIR}/msg__functions.h.em" "${rosidl_generator_c_TEMPLATE_DIR}/msg__struct.h.em" "${rosidl_generator_c_TEMPLATE_DIR}/msg__type_support.h.em" + "${rosidl_generator_c_TEMPLATE_DIR}/srv__type_support.c.em" "${rosidl_generator_c_TEMPLATE_DIR}/srv__type_support.h.em" ${rosidl_generate_interfaces_ABS_IDL_FILES} ${_dependency_files}) diff --git a/rosidl_generator_c/resource/action__type_support.c.em b/rosidl_generator_c/resource/action__type_support.c.em new file mode 100644 index 000000000..7255649d6 --- /dev/null +++ b/rosidl_generator_c/resource/action__type_support.c.em @@ -0,0 +1,14 @@ +@# Included from rosidl_generator_c/resource/idl__type_support.c.em +@{ +TEMPLATE( + 'srv__type_support.c.em', + package_name=package_name, service=action.send_goal_service, + interface_path=interface_path, include_directives=include_directives) +}@ + +@{ +TEMPLATE( + 'srv__type_support.c.em', + package_name=package_name, service=action.get_result_service, + interface_path=interface_path, include_directives=include_directives) +}@ diff --git a/rosidl_generator_c/resource/idl__functions.c.em b/rosidl_generator_c/resource/idl__functions.c.em index 86b75e507..8614665e7 100644 --- a/rosidl_generator_c/resource/idl__functions.c.em +++ b/rosidl_generator_c/resource/idl__functions.c.em @@ -64,6 +64,13 @@ TEMPLATE( package_name=package_name, interface_path=interface_path, message=service.response_message, include_directives=include_directives) }@ + +@{ +TEMPLATE( + 'msg__functions.c.em', + package_name=package_name, interface_path=interface_path, + message=service.event_message, include_directives=include_directives) +}@ @[end for]@ @ @####################################################################### @@ -109,6 +116,13 @@ TEMPLATE( message=action.send_goal_service.response_message, include_directives=include_directives) }@ +@{ +TEMPLATE( + 'msg__functions.c.em', + package_name=package_name, interface_path=interface_path, + message=action.send_goal_service.event_message, include_directives=include_directives) +}@ + @{ TEMPLATE( 'msg__functions.c.em', @@ -123,6 +137,13 @@ TEMPLATE( message=action.get_result_service.response_message, include_directives=include_directives) }@ +@{ +TEMPLATE( + 'msg__functions.c.em', + package_name=package_name, interface_path=interface_path, + message=action.get_result_service.event_message, include_directives=include_directives) +}@ + @{ TEMPLATE( 'msg__functions.c.em', diff --git a/rosidl_generator_c/resource/idl__functions.h.em b/rosidl_generator_c/resource/idl__functions.h.em index ef2a933da..ba6729df3 100644 --- a/rosidl_generator_c/resource/idl__functions.h.em +++ b/rosidl_generator_c/resource/idl__functions.h.em @@ -72,6 +72,12 @@ TEMPLATE( message=service.response_message) }@ +@{ +TEMPLATE( + 'msg__functions.h.em', + package_name=package_name, interface_path=interface_path, + message=service.event_message) +}@ @[end for]@ @ @####################################################################### @@ -116,6 +122,13 @@ TEMPLATE( message=action.send_goal_service.response_message) }@ +@{ +TEMPLATE( + 'msg__functions.h.em', + package_name=package_name, interface_path=interface_path, + message=action.send_goal_service.event_message) +}@ + @{ TEMPLATE( 'msg__functions.h.em', @@ -130,6 +143,13 @@ TEMPLATE( message=action.get_result_service.response_message) }@ +@{ +TEMPLATE( + 'msg__functions.h.em', + package_name=package_name, interface_path=interface_path, + message=action.get_result_service.event_message) +}@ + @{ TEMPLATE( 'msg__functions.h.em', diff --git a/rosidl_generator_c/resource/idl__struct.h.em b/rosidl_generator_c/resource/idl__struct.h.em index dca413791..94bf39bf4 100644 --- a/rosidl_generator_c/resource/idl__struct.h.em +++ b/rosidl_generator_c/resource/idl__struct.h.em @@ -69,6 +69,13 @@ TEMPLATE( message=service.response_message, include_directives=include_directives) }@ +@{ +TEMPLATE( + 'msg__struct.h.em', + package_name=package_name, interface_path=interface_path, + message=service.event_message, include_directives=include_directives) +}@ + @[end for]@ @ @####################################################################### @@ -113,6 +120,13 @@ TEMPLATE( message=action.send_goal_service.response_message, include_directives=include_directives) }@ +@{ +TEMPLATE( + 'msg__struct.h.em', + package_name=package_name, interface_path=interface_path, + message=action.send_goal_service.event_message, include_directives=include_directives) +}@ + @{ TEMPLATE( 'msg__struct.h.em', @@ -127,6 +141,13 @@ TEMPLATE( message=action.get_result_service.response_message, include_directives=include_directives) }@ +@{ +TEMPLATE( + 'msg__struct.h.em', + package_name=package_name, interface_path=interface_path, + message=action.get_result_service.event_message, include_directives=include_directives) +}@ + @{ TEMPLATE( 'msg__struct.h.em', diff --git a/rosidl_generator_c/resource/idl__type_support.c.em b/rosidl_generator_c/resource/idl__type_support.c.em new file mode 100644 index 000000000..77128406b --- /dev/null +++ b/rosidl_generator_c/resource/idl__type_support.c.em @@ -0,0 +1,70 @@ +// generated from rosidl_generator_c/resource/idl__type_support.c.em +// with input from @(package_name):@(interface_path) +// generated code does not contain a copyright notice +@ +@####################################################################### +@# EmPy template for generating __type_support.c 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_pycommon 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)] +include_base = '/'.join(include_parts) + +include_directives = { + 'rosidl_typesupport_interface/macros.h', + include_base + '__type_support.h', + include_base + '__struct.h', + include_base + '__functions.h'} +}@ + +#include + +@[for header_file in include_directives]@ +#include "@(header_file)" +@[end for]@ + +#ifdef __cplusplus +extern "C" +{ +#endif + +@####################################################################### +@# Handle service +@####################################################################### +@{ +from rosidl_parser.definition import Service +}@ +@[for service in content.get_elements_of_type(Service)]@ +@{ +TEMPLATE( + 'srv__type_support.c.em', + package_name=package_name, service=service, + interface_path=interface_path, 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.c.em', + package_name=package_name, action=action, + interface_path=interface_path, include_directives=include_directives) +}@ + +@[end for]@ +#ifdef __cplusplus +} +#endif diff --git a/rosidl_generator_c/resource/msg__struct.h.em b/rosidl_generator_c/resource/msg__struct.h.em index ad4b53b1e..f0b99e166 100644 --- a/rosidl_generator_c/resource/msg__struct.h.em +++ b/rosidl_generator_c/resource/msg__struct.h.em @@ -13,6 +13,8 @@ from rosidl_parser.definition import FLOATING_POINT_TYPES from rosidl_parser.definition import INTEGER_TYPES from rosidl_parser.definition import NamespacedType from rosidl_parser.definition import OCTET_TYPE +from rosidl_parser.definition import SERVICE_REQUEST_MESSAGE_SUFFIX +from rosidl_parser.definition import SERVICE_RESPONSE_MESSAGE_SUFFIX from rosidl_generator_c import basetype_to_c from rosidl_generator_c import idl_declaration_to_c from rosidl_generator_c import idl_structure_type_sequence_to_c_typename @@ -43,6 +45,14 @@ for member in message.structure.members: 'rosidl_runtime_c/u16string.h', []) member_names.append(member.name) elif isinstance(type_, NamespacedType): + if ( + message.structure.namespaced_type.namespaces[-1] in ['action', 'srv'] and ( + type_.name.endswith(SERVICE_REQUEST_MESSAGE_SUFFIX) or + type_.name.endswith(SERVICE_RESPONSE_MESSAGE_SUFFIX)) + ): + typename = type_.name.rsplit('_', 1)[0] + if typename == message.structure.namespaced_type.name.rsplit('_', 1)[0]: + continue include_prefix = idl_structure_type_to_c_include_prefix( type_, 'detail') member_names = includes.setdefault( diff --git a/rosidl_generator_c/resource/srv__type_support.c.em b/rosidl_generator_c/resource/srv__type_support.c.em new file mode 100644 index 000000000..92bb4ae50 --- /dev/null +++ b/rosidl_generator_c/resource/srv__type_support.c.em @@ -0,0 +1,82 @@ +@# Included from rosidl_generator_c/resource/srv__type_support.c.em +@{ +from rosidl_pycommon import convert_camel_case_to_lower_case_underscore +from rosidl_parser.definition import SERVICE_REQUEST_MESSAGE_SUFFIX +from rosidl_parser.definition import SERVICE_RESPONSE_MESSAGE_SUFFIX +from rosidl_parser.definition import SERVICE_EVENT_MESSAGE_SUFFIX +event_type = '__'.join([package_name, *interface_path.parents[0].parts, service.namespaced_type.name]) + SERVICE_EVENT_MESSAGE_SUFFIX +request_type = '__'.join([package_name, *interface_path.parents[0].parts, service.namespaced_type.name]) + SERVICE_REQUEST_MESSAGE_SUFFIX +response_type = '__'.join([package_name, *interface_path.parents[0].parts, service.namespaced_type.name]) + SERVICE_RESPONSE_MESSAGE_SUFFIX +} +void * +ROSIDL_TYPESUPPORT_INTERFACE__SERVICE_CREATE_EVENT_MESSAGE_SYMBOL_NAME( + rosidl_typesupport_c, + @(',\n '.join(service.namespaced_type.namespaced_name())) +)( + const rosidl_service_introspection_info_t * info, + rcutils_allocator_t * allocator, + const void * request_message, + const void * response_message) +{ + if (!allocator || !info) { + return NULL; + } + @event_type * event_msg = (@event_type *)(allocator->allocate(sizeof(@event_type), allocator->state)); + if (!@(event_type)__init(event_msg)) { + allocator->deallocate(event_msg, allocator->state); + return NULL; + } + + event_msg->info.event_type = info->event_type; + event_msg->info.sequence_number = info->sequence_number; + event_msg->info.stamp.sec = info->stamp_sec; + event_msg->info.stamp.nanosec = info->stamp_nanosec; + memcpy(event_msg->info.client_gid, info->client_gid, 16); + if (request_message) { + @(request_type)__Sequence__init( + &event_msg->request, + 1); + if (!@(request_type)__copy((const @request_type *)(request_message), event_msg->request.data)) { + allocator->deallocate(event_msg, allocator->state); + return NULL; + } + } + if (response_message) { + @(response_type)__Sequence__init( + &event_msg->response, + 1); + if (!@(response_type)__copy((const @response_type *)(response_message), event_msg->response.data)) { + allocator->deallocate(event_msg, allocator->state); + return NULL; + } + } + return event_msg; +} + +// Forward declare the get type support functions for this type. +bool +ROSIDL_TYPESUPPORT_INTERFACE__SERVICE_DESTROY_EVENT_MESSAGE_SYMBOL_NAME( + rosidl_typesupport_c, + @(',\n '.join(service.namespaced_type.namespaced_name())) +)( + void * event_msg, + rcutils_allocator_t * allocator) +{ + if (!allocator) { + return false; + } + if (NULL == event_msg) { + return false; + } + @event_type * _event_msg = (@event_type *)(event_msg); + + @(event_type)__fini((@event_type *)(_event_msg)); + if (_event_msg->request.data) { + allocator->deallocate(_event_msg->request.data, allocator->state); + } + if (_event_msg->response.data) { + allocator->deallocate(_event_msg->response.data, allocator->state); + } + allocator->deallocate(_event_msg, allocator->state); + return true; +} diff --git a/rosidl_generator_c/resource/srv__type_support.h.em b/rosidl_generator_c/resource/srv__type_support.h.em index c6108cb5b..af2621cfc 100644 --- a/rosidl_generator_c/resource/srv__type_support.h.em +++ b/rosidl_generator_c/resource/srv__type_support.h.em @@ -13,6 +13,13 @@ TEMPLATE( include_directives=include_directives) }@ +@{ +TEMPLATE( + 'msg__type_support.h.em', + package_name=package_name, message=service.event_message, + include_directives=include_directives) +}@ + @{header_file = 'rosidl_runtime_c/service_type_support_struct.h'}@ @[if header_file in include_directives]@ // already included above @@ -29,3 +36,25 @@ ROSIDL_TYPESUPPORT_INTERFACE__SERVICE_SYMBOL_NAME( rosidl_typesupport_c, @(',\n '.join(service.namespaced_type.namespaced_name())) )(); + +// Forward declare the function to create a service event message for this type. +ROSIDL_GENERATOR_C_PUBLIC_@(package_name) +void * +ROSIDL_TYPESUPPORT_INTERFACE__SERVICE_CREATE_EVENT_MESSAGE_SYMBOL_NAME( + rosidl_typesupport_c, + @(',\n '.join(service.namespaced_type.namespaced_name())) +)( + const rosidl_service_introspection_info_t * info, + rcutils_allocator_t * allocator, + const void * request_message, + const void * response_message); + +// Forward declare the function to destroy a service event message for this type. +ROSIDL_GENERATOR_C_PUBLIC_@(package_name) +bool +ROSIDL_TYPESUPPORT_INTERFACE__SERVICE_DESTROY_EVENT_MESSAGE_SYMBOL_NAME( + rosidl_typesupport_c, + @(',\n '.join(service.namespaced_type.namespaced_name())) +)( + void * event_msg, + rcutils_allocator_t * allocator); diff --git a/rosidl_generator_c/rosidl_generator_c/__init__.py b/rosidl_generator_c/rosidl_generator_c/__init__.py index 02aa5e884..17071b67f 100644 --- a/rosidl_generator_c/rosidl_generator_c/__init__.py +++ b/rosidl_generator_c/rosidl_generator_c/__init__.py @@ -32,6 +32,7 @@ def generate_c(generator_arguments_file): 'idl__functions.c.em': 'detail/%s__functions.c', 'idl__functions.h.em': 'detail/%s__functions.h', 'idl__struct.h.em': 'detail/%s__struct.h', + 'idl__type_support.c.em': 'detail/%s__type_support.c', 'idl__type_support.h.em': 'detail/%s__type_support.h', } return generate_files( diff --git a/rosidl_generator_cpp/resource/msg__struct.hpp.em b/rosidl_generator_cpp/resource/msg__struct.hpp.em index 5f8a82c82..02097f15e 100644 --- a/rosidl_generator_cpp/resource/msg__struct.hpp.em +++ b/rosidl_generator_cpp/resource/msg__struct.hpp.em @@ -11,6 +11,8 @@ from rosidl_parser.definition import AbstractWString from rosidl_parser.definition import ACTION_FEEDBACK_SUFFIX from rosidl_parser.definition import ACTION_GOAL_SUFFIX from rosidl_parser.definition import ACTION_RESULT_SUFFIX +from rosidl_parser.definition import SERVICE_REQUEST_MESSAGE_SUFFIX +from rosidl_parser.definition import SERVICE_RESPONSE_MESSAGE_SUFFIX from rosidl_parser.definition import BasicType from rosidl_parser.definition import BOOLEAN_TYPE from rosidl_parser.definition import CHARACTER_TYPES @@ -37,6 +39,14 @@ for member in message.structure.members: if isinstance(type_, AbstractNestedType): type_ = type_.value_type if isinstance(type_, NamespacedType): + if ( + message.structure.namespaced_type.namespaces[-1] in ['action', 'srv'] and ( + type_.name.endswith(SERVICE_REQUEST_MESSAGE_SUFFIX) or + type_.name.endswith(SERVICE_RESPONSE_MESSAGE_SUFFIX)) + ): + typename = type_.name.rsplit('_', 1)[0] + if typename == message.structure.namespaced_type.name.rsplit('_', 1)[0]: + continue if ( type_.name.endswith(ACTION_GOAL_SUFFIX) or type_.name.endswith(ACTION_RESULT_SUFFIX) or diff --git a/rosidl_generator_cpp/resource/msg__traits.hpp.em b/rosidl_generator_cpp/resource/msg__traits.hpp.em index 9fa1923dd..7381f2869 100644 --- a/rosidl_generator_cpp/resource/msg__traits.hpp.em +++ b/rosidl_generator_cpp/resource/msg__traits.hpp.em @@ -3,6 +3,8 @@ from rosidl_parser.definition import ACTION_FEEDBACK_SUFFIX from rosidl_parser.definition import ACTION_GOAL_SUFFIX from rosidl_parser.definition import ACTION_RESULT_SUFFIX +from rosidl_parser.definition import SERVICE_REQUEST_MESSAGE_SUFFIX +from rosidl_parser.definition import SERVICE_RESPONSE_MESSAGE_SUFFIX from rosidl_parser.definition import Array from rosidl_parser.definition import AbstractGenericString from rosidl_parser.definition import BasicType @@ -28,6 +30,14 @@ for member in message.structure.members: if isinstance(type_, (AbstractSequence, Array)): type_ = type_.value_type if isinstance(type_, NamespacedType): + if ( + message.structure.namespaced_type.namespaces[-1] in ['action', 'srv'] and ( + type_.name.endswith(SERVICE_REQUEST_MESSAGE_SUFFIX) or + type_.name.endswith(SERVICE_RESPONSE_MESSAGE_SUFFIX)) + ): + typename = type_.name.rsplit('_', 1)[0] + if typename == message.structure.namespaced_type.name.rsplit('_', 1)[0]: + continue if ( type_.name.endswith(ACTION_GOAL_SUFFIX) or type_.name.endswith(ACTION_RESULT_SUFFIX) or diff --git a/rosidl_generator_cpp/resource/srv__builder.hpp.em b/rosidl_generator_cpp/resource/srv__builder.hpp.em index feca7be94..40778af04 100644 --- a/rosidl_generator_cpp/resource/srv__builder.hpp.em +++ b/rosidl_generator_cpp/resource/srv__builder.hpp.em @@ -12,3 +12,10 @@ TEMPLATE( package_name=package_name, interface_path=interface_path, message=service.response_message, include_directives=include_directives) }@ + +@{ +TEMPLATE( + 'msg__builder.hpp.em', + package_name=package_name, interface_path=interface_path, + message=service.event_message, include_directives=include_directives) +}@ diff --git a/rosidl_generator_cpp/resource/srv__struct.hpp.em b/rosidl_generator_cpp/resource/srv__struct.hpp.em index 12744269a..1466c9980 100644 --- a/rosidl_generator_cpp/resource/srv__struct.hpp.em +++ b/rosidl_generator_cpp/resource/srv__struct.hpp.em @@ -13,6 +13,13 @@ TEMPLATE( message=service.response_message, include_directives=include_directives) }@ +@{ +TEMPLATE( + 'msg__struct.hpp.em', + package_name=package_name, interface_path=interface_path, + message=service.event_message, include_directives=include_directives) +}@ + @[for ns in service.namespaced_type.namespaces]@ namespace @(ns) { @@ -26,6 +33,7 @@ service_typename = '::'.join(service.namespaced_type.namespaced_name()) }@ using Request = @(service_typename)_Request; using Response = @(service_typename)_Response; + using Event = @(service_typename)_Event; }; @ @[for ns in reversed(service.namespaced_type.namespaces)]@ diff --git a/rosidl_generator_cpp/resource/srv__traits.hpp.em b/rosidl_generator_cpp/resource/srv__traits.hpp.em index 03326754b..3000565e0 100644 --- a/rosidl_generator_cpp/resource/srv__traits.hpp.em +++ b/rosidl_generator_cpp/resource/srv__traits.hpp.em @@ -13,6 +13,13 @@ TEMPLATE( message=service.response_message, include_directives=include_directives) }@ +@{ +TEMPLATE( + 'msg__traits.hpp.em', + package_name=package_name, interface_path=interface_path, + message=service.event_message, include_directives=include_directives) +}@ + @{ service_typename = '::'.join(service.namespaced_type.namespaced_name()) service_fully_qualified_name = '/'.join(service.namespaced_type.namespaced_name()) diff --git a/rosidl_generator_tests/package.xml b/rosidl_generator_tests/package.xml index 9c6d716af..06b3a47ba 100644 --- a/rosidl_generator_tests/package.xml +++ b/rosidl_generator_tests/package.xml @@ -27,6 +27,7 @@ rosidl_runtime_c rosidl_runtime_cpp test_interface_files + service_msgs ament_cmake diff --git a/rosidl_generator_tests/test/rosidl_generator_cpp/test_srv_initialization.cpp b/rosidl_generator_tests/test/rosidl_generator_cpp/test_srv_initialization.cpp index c774b9466..f4cbdd366 100644 --- a/rosidl_generator_tests/test/rosidl_generator_cpp/test_srv_initialization.cpp +++ b/rosidl_generator_tests/test/rosidl_generator_cpp/test_srv_initialization.cpp @@ -24,7 +24,7 @@ TEST(Test_srv_initialization, no_arg_request_constructor) { EXPECT_EQ(false, basic_types.bool_value); EXPECT_EQ(0, basic_types.byte_value); EXPECT_EQ(0, basic_types.char_value); - EXPECT_EQ(0.0f, basic_types.float32_value); + EXPECT_EQ(0.0F, basic_types.float32_value); EXPECT_EQ(0.0, basic_types.float64_value); EXPECT_EQ(0, basic_types.int8_value); EXPECT_EQ(0u, basic_types.uint8_value); @@ -57,6 +57,19 @@ TEST(Test_srv_initialization, no_arg_response_constructor) { EXPECT_EQ("", basic_types.string_value); } +TEST(Test_srv_initialization, no_arg_event_constructor) { + rosidl_generator_tests::srv::Empty::Event empty; + + rosidl_generator_tests::srv::BasicTypes::Event basic_types; + EXPECT_EQ(basic_types.info.event_type, 0u); + EXPECT_EQ(basic_types.info.stamp.sec, 0); + EXPECT_EQ(basic_types.info.stamp.nanosec, 0u); + for (auto i : basic_types.info.client_gid) { + EXPECT_EQ(i, 0u); + } + EXPECT_EQ(basic_types.request.size(), 0u); + EXPECT_EQ(basic_types.response.size(), 0u); +} // Note that we very specifically don't add tests for some of the other // possibilities here (bounded strings, bounded / unbounded arrays, other // initialization parameters, etc). That's because that is all tested in diff --git a/rosidl_generator_tests/test/rosidl_generator_cpp/test_traits.cpp b/rosidl_generator_tests/test/rosidl_generator_cpp/test_traits.cpp index 0b79fee6f..7e16d450c 100644 --- a/rosidl_generator_tests/test/rosidl_generator_cpp/test_traits.cpp +++ b/rosidl_generator_tests/test/rosidl_generator_cpp/test_traits.cpp @@ -406,6 +406,7 @@ TEST(Test_rosidl_generator_traits, is_service) { using Service = rosidl_generator_tests::srv::Empty; using ServiceReq = Service::Request; using ServiceResp = Service::Response; + using ServiceEvent = Service::Event; EXPECT_TRUE(is_service()); EXPECT_FALSE(is_message()); @@ -423,4 +424,10 @@ TEST(Test_rosidl_generator_traits, is_service) { EXPECT_TRUE(is_message()); EXPECT_FALSE(is_service_request()); EXPECT_TRUE(is_service_response()); + + // Events are additionally messages + EXPECT_FALSE(is_service()); + EXPECT_TRUE(is_message()); + EXPECT_FALSE(is_service_request()); + EXPECT_FALSE(is_service_response()); } diff --git a/rosidl_parser/rosidl_parser/definition.py b/rosidl_parser/rosidl_parser/definition.py index 20b6f7af8..689b71384 100644 --- a/rosidl_parser/rosidl_parser/definition.py +++ b/rosidl_parser/rosidl_parser/definition.py @@ -91,6 +91,7 @@ SERVICE_REQUEST_MESSAGE_SUFFIX = '_Request' SERVICE_RESPONSE_MESSAGE_SUFFIX = '_Response' +SERVICE_EVENT_MESSAGE_SUFFIX = '_Event' ACTION_GOAL_SUFFIX = '_Goal' ACTION_RESULT_SUFFIX = '_Result' @@ -562,7 +563,7 @@ def __init__(self, structure: Structure): class Service: """A namespaced type containing a request and response message.""" - __slots__ = ('namespaced_type', 'request_message', 'response_message') + __slots__ = ('namespaced_type', 'request_message', 'response_message', 'event_message') def __init__( self, namespaced_type: NamespacedType, request: Message, @@ -595,6 +596,20 @@ def __init__( namespaced_type.name + SERVICE_RESPONSE_MESSAGE_SUFFIX self.response_message = response + self.event_message = Message( + Structure( + NamespacedType( + namespaces=namespaced_type.namespaces, + name=f'{namespaced_type.name}{SERVICE_EVENT_MESSAGE_SUFFIX}' + ), + members=[ + Member(NamespacedType(['service_msgs', 'msg'], 'ServiceEventInfo'), 'info'), + Member(BoundedSequence(request.structure.namespaced_type, 1), 'request'), + Member(BoundedSequence(response.structure.namespaced_type, 1), 'response'), + ] + ) + ) + class Action: """A namespaced type of an action including the derived types.""" diff --git a/rosidl_parser/test/test_parser.py b/rosidl_parser/test/test_parser.py index 988032c5a..90fc38696 100644 --- a/rosidl_parser/test/test_parser.py +++ b/rosidl_parser/test/test_parser.py @@ -15,7 +15,6 @@ import pathlib import pytest - from rosidl_parser.definition import Action from rosidl_parser.definition import Array from rosidl_parser.definition import BasicType @@ -27,6 +26,7 @@ from rosidl_parser.definition import Message from rosidl_parser.definition import NamespacedType from rosidl_parser.definition import Service +from rosidl_parser.definition import SERVICE_EVENT_MESSAGE_SUFFIX from rosidl_parser.definition import UnboundedSequence from rosidl_parser.definition import UnboundedString from rosidl_parser.definition import UnboundedWString @@ -315,6 +315,13 @@ def test_service_parser(service_idl_file): assert srv.namespaced_type.name == 'MyService' assert len(srv.request_message.structure.members) == 2 assert len(srv.response_message.structure.members) == 1 + assert(srv.event_message.structure.namespaced_type.name == + 'MyService' + SERVICE_EVENT_MESSAGE_SUFFIX) + + event_message_members = [i.name for i in srv.event_message.structure.members] + assert('request' in event_message_members) + assert('response' in event_message_members) + assert('info' in event_message_members) constants = srv.request_message.constants assert len(constants) == 1 diff --git a/rosidl_runtime_c/include/rosidl_runtime_c/service_type_support_struct.h b/rosidl_runtime_c/include/rosidl_runtime_c/service_type_support_struct.h index 368c94f03..2039d819c 100644 --- a/rosidl_runtime_c/include/rosidl_runtime_c/service_type_support_struct.h +++ b/rosidl_runtime_c/include/rosidl_runtime_c/service_type_support_struct.h @@ -15,6 +15,10 @@ #ifndef ROSIDL_RUNTIME_C__SERVICE_TYPE_SUPPORT_STRUCT_H_ #define ROSIDL_RUNTIME_C__SERVICE_TYPE_SUPPORT_STRUCT_H_ +#include + +#include "rcutils/allocator.h" +#include "rosidl_runtime_c/message_type_support_struct.h" #include "rosidl_runtime_c/visibility_control.h" #include "rosidl_typesupport_interface/macros.h" @@ -29,6 +33,45 @@ typedef struct rosidl_service_type_support_t rosidl_service_type_support_t; typedef const rosidl_service_type_support_t * (* rosidl_service_typesupport_handle_function)( const rosidl_service_type_support_t *, const char *); +typedef struct rosidl_service_introspection_info_s +{ + uint8_t event_type; + int32_t stamp_sec; + uint32_t stamp_nanosec; + uint8_t client_gid[16]; + int64_t sequence_number; +} rosidl_service_introspection_info_t; + +/// Creates a ServiceEvent message for the service. +/** + * Instantiates a ServiceEvent message with the given info and request/response message. + * The message is allocated using the given allocator and must be deallocated using + * the rosidl_service_introspection_destroy_handle + * + * \param[in] info POD fields of service_msgs/msg/ServiceEventInfo to be passed from rcl + * \param[in] allocator The allocator to use for allocating the ServiceEvent message + * \param[in] request_message type-erased handle to request message from rcl. Can be NULL. + * \param[in] response_message type-erased handle to request message from rcl. Can be NULL. + * \return The built ServiceEvent message. Will return NULL if the message could not be built. + **/ +typedef void * (* rosidl_event_message_create_handle_function_function)( + const rosidl_service_introspection_info_t * info, + rcutils_allocator_t * allocator, + const void * request_message, + const void * response_message); + +/// Destroys a ServiceEvent message +/** + * Destroys a ServiceEvent message returned by a rosidl_service_introspection_message_create_handle + * by calling the corresponding __fini function then deallocating + * + * \param[in] event_message The message to destroy. + * \param[in] allocator The allocator to use for deallocating the message. + */ +typedef bool (* rosidl_event_message_destroy_handle_function_function)( + void * event_message, + rcutils_allocator_t * allocator); + /// Contains rosidl service type support data struct rosidl_service_type_support_t { @@ -38,6 +81,12 @@ struct rosidl_service_type_support_t const void * data; /// Pointer to the service type support handler function rosidl_service_typesupport_handle_function func; + /// Pointer to function to create the introspection message + rosidl_event_message_create_handle_function_function event_message_create_handle_function; + /// Pointer to function to finalize the introspection message + rosidl_event_message_destroy_handle_function_function event_message_destroy_handle_function; + /// Service event message typesupport + const rosidl_message_type_support_t * event_typesupport; }; /// Get the service type support handle specific to this identifier. diff --git a/rosidl_runtime_cpp/include/rosidl_typesupport_cpp/service_type_support.hpp b/rosidl_runtime_cpp/include/rosidl_typesupport_cpp/service_type_support.hpp index d0fc4e58e..2931b8736 100644 --- a/rosidl_runtime_cpp/include/rosidl_typesupport_cpp/service_type_support.hpp +++ b/rosidl_runtime_cpp/include/rosidl_typesupport_cpp/service_type_support.hpp @@ -15,8 +15,11 @@ #ifndef ROSIDL_TYPESUPPORT_CPP__SERVICE_TYPE_SUPPORT_HPP_ #define ROSIDL_TYPESUPPORT_CPP__SERVICE_TYPE_SUPPORT_HPP_ -#include -#include +#include +#include + +#include "rosidl_runtime_c/service_type_support_struct.h" +#include "rosidl_runtime_c/visibility_control.h" namespace rosidl_typesupport_cpp { @@ -24,6 +27,54 @@ namespace rosidl_typesupport_cpp template const rosidl_service_type_support_t * get_service_type_support_handle(); +template +void * service_create_event_message( + const rosidl_service_introspection_info_t * info, + rcutils_allocator_t * allocator, + const void * request_message, + const void * response_message) +{ + if (nullptr == info) { + throw std::invalid_argument("service introspection info struct cannot be null"); + } + if (nullptr == allocator) { + throw std::invalid_argument("allocator cannot be null"); + } + auto * event_msg = static_cast( + allocator->allocate(sizeof(typename T::Event), allocator->state)); + if (nullptr == event_msg) { + throw std::invalid_argument("allocation failed for service event message"); + } + event_msg = new(event_msg) typename T::Event(); + + event_msg->info.set__event_type(info->event_type); + event_msg->info.set__sequence_number(info->sequence_number); + event_msg->info.stamp.set__sec(info->stamp_sec); + event_msg->info.stamp.set__nanosec(info->stamp_nanosec); + + std::memcpy(&event_msg->info.client_gid[0], info->client_gid, 16); + + if (nullptr != request_message) { + event_msg->request.push_back(*static_cast(request_message)); + } + if (nullptr != response_message) { + event_msg->response.push_back(*static_cast(response_message)); + } + return event_msg; +} + +template +bool service_destroy_event_message( + void * event_msg, + rcutils_allocator_t * allocator) +{ + auto * event_msg_ = static_cast(event_msg); + using EventT = typename T::Event; + event_msg_->~EventT(); + allocator->deallocate(event_msg, allocator->state); + return true; +} + } // namespace rosidl_typesupport_cpp #endif // ROSIDL_TYPESUPPORT_CPP__SERVICE_TYPE_SUPPORT_HPP_ diff --git a/rosidl_typesupport_interface/include/rosidl_typesupport_interface/macros.h b/rosidl_typesupport_interface/include/rosidl_typesupport_interface/macros.h index aa619b252..de3fbef41 100644 --- a/rosidl_typesupport_interface/include/rosidl_typesupport_interface/macros.h +++ b/rosidl_typesupport_interface/include/rosidl_typesupport_interface/macros.h @@ -47,4 +47,16 @@ typesupport_name, get_action_type_support_handle, \ package_name, interface_type, action_name) +#define ROSIDL_TYPESUPPORT_INTERFACE__SERVICE_CREATE_EVENT_MESSAGE_SYMBOL_NAME( \ + typesupport_name, package_name, interface_type, service_name) \ + ROSIDL_TYPESUPPORT_INTERFACE__SYMBOL_NAME( \ + typesupport_name, create_service_event_message, \ + package_name, interface_type, service_name) + +#define ROSIDL_TYPESUPPORT_INTERFACE__SERVICE_DESTROY_EVENT_MESSAGE_SYMBOL_NAME( \ + typesupport_name, package_name, interface_type, service_name) \ + ROSIDL_TYPESUPPORT_INTERFACE__SYMBOL_NAME( \ + typesupport_name, destroy_service_event_message, \ + package_name, interface_type, service_name) + #endif // ROSIDL_TYPESUPPORT_INTERFACE__MACROS_H_ diff --git a/rosidl_typesupport_introspection_c/include/rosidl_typesupport_introspection_c/service_introspection.h b/rosidl_typesupport_introspection_c/include/rosidl_typesupport_introspection_c/service_introspection.h index 059ab00fc..ea57dffd6 100644 --- a/rosidl_typesupport_introspection_c/include/rosidl_typesupport_introspection_c/service_introspection.h +++ b/rosidl_typesupport_introspection_c/include/rosidl_typesupport_introspection_c/service_introspection.h @@ -36,6 +36,8 @@ typedef struct rosidl_typesupport_introspection_c__ServiceMembers_s const rosidl_typesupport_introspection_c__MessageMembers * request_members_; /// A pointer to the introspection information structure for the response interface. const rosidl_typesupport_introspection_c__MessageMembers * response_members_; + /// A pointer to the introspection information structure for the event interface. + const rosidl_typesupport_introspection_c__MessageMembers * event_members_; } rosidl_typesupport_introspection_c__ServiceMembers; #endif // ROSIDL_TYPESUPPORT_INTROSPECTION_C__SERVICE_INTROSPECTION_H_ diff --git a/rosidl_typesupport_introspection_c/resource/srv__rosidl_typesupport_introspection_c.h.em b/rosidl_typesupport_introspection_c/resource/srv__rosidl_typesupport_introspection_c.h.em index 360ea1f7e..c686b8aea 100644 --- a/rosidl_typesupport_introspection_c/resource/srv__rosidl_typesupport_introspection_c.h.em +++ b/rosidl_typesupport_introspection_c/resource/srv__rosidl_typesupport_introspection_c.h.em @@ -13,6 +13,13 @@ TEMPLATE( include_directives=include_directives) }@ +@{ +TEMPLATE( + 'msg__rosidl_typesupport_introspection_c.h.em', + package_name=package_name, interface_path=interface_path, message=service.event_message, + include_directives=include_directives) +}@ + @{ header_files = [ 'rosidl_runtime_c/service_type_support_struct.h', diff --git a/rosidl_typesupport_introspection_c/resource/srv__type_support.c.em b/rosidl_typesupport_introspection_c/resource/srv__type_support.c.em index 3922e5830..1158d9f50 100644 --- a/rosidl_typesupport_introspection_c/resource/srv__type_support.c.em +++ b/rosidl_typesupport_introspection_c/resource/srv__type_support.c.em @@ -13,8 +13,18 @@ TEMPLATE( include_directives=include_directives) }@ +@{ +TEMPLATE( + 'msg__type_support.c.em', + package_name=package_name, interface_path=interface_path, message=service.event_message, + include_directives=include_directives) +}@ + @{ from rosidl_pycommon import convert_camel_case_to_lower_case_underscore +from rosidl_parser.definition import SERVICE_REQUEST_MESSAGE_SUFFIX +from rosidl_parser.definition import SERVICE_RESPONSE_MESSAGE_SUFFIX +from rosidl_parser.definition import SERVICE_EVENT_MESSAGE_SUFFIX include_parts = [package_name] + list(interface_path.parents[0].parts) + [ 'detail', convert_camel_case_to_lower_case_underscore(interface_path.stem)] include_base = '/'.join(include_parts) @@ -27,6 +37,7 @@ header_files = [ 'rosidl_typesupport_introspection_c/service_introspection.h', ] +message_function_prefix = '__'.join([package_name] + list(interface_path.parents[0].parts) + [service.namespaced_type.name]) + f'{SERVICE_EVENT_MESSAGE_SUFFIX}__rosidl_typesupport_introspection_c' function_prefix = '__'.join(include_parts) + '__rosidl_typesupport_introspection_c' }@ @[for header_file in header_files]@ @@ -46,22 +57,40 @@ static rosidl_typesupport_introspection_c__ServiceMembers @(function_prefix)__@( // these two fields are initialized below on the first access NULL, // request message // @(function_prefix)__@(service.request_message.structure.namespaced_type.name)_message_type_support_handle, - NULL // response message + NULL, // response message + // @(function_prefix)__@(service.response_message.structure.namespaced_type.name)_message_type_support_handle + NULL // event_message // @(function_prefix)__@(service.response_message.structure.namespaced_type.name)_message_type_support_handle }; +@{event_type = '__'.join([package_name, *interface_path.parents[0].parts, service.namespaced_type.name]) + SERVICE_EVENT_MESSAGE_SUFFIX}@ +@{request_type = '__'.join([package_name, *interface_path.parents[0].parts, service.namespaced_type.name]) + SERVICE_REQUEST_MESSAGE_SUFFIX}@ +@{response_type = '__'.join([package_name, *interface_path.parents[0].parts, service.namespaced_type.name]) + SERVICE_RESPONSE_MESSAGE_SUFFIX}@ + static rosidl_service_type_support_t @(function_prefix)__@(service.namespaced_type.name)_service_type_support_handle = { 0, &@(function_prefix)__@(service.namespaced_type.name)_service_members, get_service_typesupport_handle_function, + ROSIDL_TYPESUPPORT_INTERFACE__SERVICE_CREATE_EVENT_MESSAGE_SYMBOL_NAME( + rosidl_typesupport_c, + @(',\n '.join(service.namespaced_type.namespaced_name())) + ), + ROSIDL_TYPESUPPORT_INTERFACE__SERVICE_DESTROY_EVENT_MESSAGE_SYMBOL_NAME( + rosidl_typesupport_c, + @(',\n '.join(service.namespaced_type.namespaced_name())) + ), + &@(message_function_prefix)__@(service.namespaced_type.name)@(SERVICE_EVENT_MESSAGE_SUFFIX)_message_type_support_handle, }; // Forward declaration of request/response type support functions const rosidl_message_type_support_t * -ROSIDL_TYPESUPPORT_INTERFACE__MESSAGE_SYMBOL_NAME(rosidl_typesupport_introspection_c, @(', '.join([package_name] + list(interface_path.parents[0].parts))), @(service.namespaced_type.name)_Request)(); +ROSIDL_TYPESUPPORT_INTERFACE__MESSAGE_SYMBOL_NAME(rosidl_typesupport_introspection_c, @(', '.join([package_name] + list(interface_path.parents[0].parts))), @(service.namespaced_type.name + SERVICE_REQUEST_MESSAGE_SUFFIX))(); + +const rosidl_message_type_support_t * +ROSIDL_TYPESUPPORT_INTERFACE__MESSAGE_SYMBOL_NAME(rosidl_typesupport_introspection_c, @(', '.join([package_name] + list(interface_path.parents[0].parts))), @(service.namespaced_type.name + SERVICE_RESPONSE_MESSAGE_SUFFIX))(); const rosidl_message_type_support_t * -ROSIDL_TYPESUPPORT_INTERFACE__MESSAGE_SYMBOL_NAME(rosidl_typesupport_introspection_c, @(', '.join([package_name] + list(interface_path.parents[0].parts))), @(service.namespaced_type.name)_Response)(); +ROSIDL_TYPESUPPORT_INTERFACE__MESSAGE_SYMBOL_NAME(rosidl_typesupport_introspection_c, @(', '.join([package_name] + list(interface_path.parents[0].parts))), @(service.namespaced_type.name + SERVICE_EVENT_MESSAGE_SUFFIX))(); ROSIDL_TYPESUPPORT_INTROSPECTION_C_EXPORT_@(package_name) const rosidl_service_type_support_t * @@ -76,12 +105,17 @@ ROSIDL_TYPESUPPORT_INTERFACE__SERVICE_SYMBOL_NAME(rosidl_typesupport_introspecti if (!service_members->request_members_) { service_members->request_members_ = (const rosidl_typesupport_introspection_c__MessageMembers *) - ROSIDL_TYPESUPPORT_INTERFACE__MESSAGE_SYMBOL_NAME(rosidl_typesupport_introspection_c, @(', '.join([package_name] + list(interface_path.parents[0].parts))), @(service.namespaced_type.name)_Request)()->data; + ROSIDL_TYPESUPPORT_INTERFACE__MESSAGE_SYMBOL_NAME(rosidl_typesupport_introspection_c, @(', '.join([package_name] + list(interface_path.parents[0].parts))), @(service.namespaced_type.name + SERVICE_REQUEST_MESSAGE_SUFFIX))()->data; } if (!service_members->response_members_) { service_members->response_members_ = (const rosidl_typesupport_introspection_c__MessageMembers *) - ROSIDL_TYPESUPPORT_INTERFACE__MESSAGE_SYMBOL_NAME(rosidl_typesupport_introspection_c, @(', '.join([package_name] + list(interface_path.parents[0].parts))), @(service.namespaced_type.name)_Response)()->data; + ROSIDL_TYPESUPPORT_INTERFACE__MESSAGE_SYMBOL_NAME(rosidl_typesupport_introspection_c, @(', '.join([package_name] + list(interface_path.parents[0].parts))), @(service.namespaced_type.name + SERVICE_RESPONSE_MESSAGE_SUFFIX))()->data; + } + if (!service_members->event_members_) { + service_members->event_members_ = + (const rosidl_typesupport_introspection_c__MessageMembers *) + ROSIDL_TYPESUPPORT_INTERFACE__MESSAGE_SYMBOL_NAME(rosidl_typesupport_introspection_c, @(', '.join([package_name] + list(interface_path.parents[0].parts))), @(service.namespaced_type.name + SERVICE_EVENT_MESSAGE_SUFFIX))()->data; } return &@(function_prefix)__@(service.namespaced_type.name)_service_type_support_handle; diff --git a/rosidl_typesupport_introspection_cpp/include/rosidl_typesupport_introspection_cpp/service_introspection.hpp b/rosidl_typesupport_introspection_cpp/include/rosidl_typesupport_introspection_cpp/service_introspection.hpp index df6f910d8..cad7e04e8 100644 --- a/rosidl_typesupport_introspection_cpp/include/rosidl_typesupport_introspection_cpp/service_introspection.hpp +++ b/rosidl_typesupport_introspection_cpp/include/rosidl_typesupport_introspection_cpp/service_introspection.hpp @@ -39,6 +39,8 @@ typedef struct ServiceMembers_s const MessageMembers * request_members_; /// A pointer to the introspection information structure for the response interface. const MessageMembers * response_members_; + /// A pointer to the introspection information structure for the event interface. + const MessageMembers * event_members_; } ServiceMembers; } // namespace rosidl_typesupport_introspection_cpp diff --git a/rosidl_typesupport_introspection_cpp/resource/srv__type_support.cpp.em b/rosidl_typesupport_introspection_cpp/resource/srv__type_support.cpp.em index 0e2883e1d..bce36658a 100644 --- a/rosidl_typesupport_introspection_cpp/resource/srv__type_support.cpp.em +++ b/rosidl_typesupport_introspection_cpp/resource/srv__type_support.cpp.em @@ -13,14 +13,23 @@ TEMPLATE( include_directives=include_directives) }@ +@{ +TEMPLATE( + 'msg__type_support.cpp.em', + package_name=package_name, interface_path=interface_path, message=service.event_message, + include_directives=include_directives) +}@ + @{ from rosidl_pycommon import convert_camel_case_to_lower_case_underscore +from rosidl_parser.definition import SERVICE_REQUEST_MESSAGE_SUFFIX +from rosidl_parser.definition import SERVICE_RESPONSE_MESSAGE_SUFFIX +from rosidl_parser.definition import SERVICE_EVENT_MESSAGE_SUFFIX include_parts = [package_name] + list(interface_path.parents[0].parts) + [ 'detail', convert_camel_case_to_lower_case_underscore(interface_path.stem)] include_base = '/'.join(include_parts) header_files = [ - 'rosidl_runtime_c/service_type_support_struct.h', 'rosidl_typesupport_cpp/message_type_support.hpp', 'rosidl_typesupport_cpp/service_type_support.hpp', 'rosidl_typesupport_interface/macros.h', @@ -57,13 +66,17 @@ static ::rosidl_typesupport_introspection_cpp::ServiceMembers @(service.namespac // these two fields are initialized below on the first access // see get_service_type_support_handle<@('::'.join([package_name] + list(interface_path.parents[0].parts) + [service.namespaced_type.name]))>() nullptr, // request message - nullptr // response message + nullptr, // response message + nullptr, // event message }; static const rosidl_service_type_support_t @(service.namespaced_type.name)_service_type_support_handle = { ::rosidl_typesupport_introspection_cpp::typesupport_identifier, &@(service.namespaced_type.name)_service_members, get_service_typesupport_handle_function, + &::rosidl_typesupport_cpp::service_create_event_message<@('::'.join([package_name, *interface_path.parents[0].parts, service.namespaced_type.name]))>, + &::rosidl_typesupport_cpp::service_destroy_event_message<@('::'.join([package_name, *interface_path.parents[0].parts, service.namespaced_type.name]))>, + ::rosidl_typesupport_introspection_cpp::get_message_type_support_handle<@('::'.join([package_name, *interface_path.parents[0].parts, service.namespaced_type.name]))_Event>(), }; } // namespace rosidl_typesupport_introspection_cpp @@ -92,7 +105,8 @@ get_service_type_support_handle<@('::'.join([package_name] + list(interface_path // if they are not, initialize them if ( service_members->request_members_ == nullptr || - service_members->response_members_ == nullptr) + service_members->response_members_ == nullptr || + service_members->event_members_ == nullptr) { // initialize the request_members_ with the static function from the external library service_members->request_members_ = static_cast< @@ -110,6 +124,15 @@ get_service_type_support_handle<@('::'.join([package_name] + list(interface_path ::@('::'.join([package_name] + list(interface_path.parents[0].parts)))::@(service.response_message.structure.namespaced_type.name) >()->data ); + + // initialize the event_members_ with the static function from the external library + service_members->event_members_ = static_cast< + const ::rosidl_typesupport_introspection_cpp::MessageMembers * + >( + ::rosidl_typesupport_introspection_cpp::get_message_type_support_handle< + ::@('::'.join([package_name] + list(interface_path.parents[0].parts)))::@(service.event_message.structure.namespaced_type.name) + >()->data + ); } // finally return the properly initialized service_type_support handle return service_type_support; diff --git a/rosidl_typesupport_introspection_tests/package.xml b/rosidl_typesupport_introspection_tests/package.xml index b5aa95a92..3463aba69 100644 --- a/rosidl_typesupport_introspection_tests/package.xml +++ b/rosidl_typesupport_introspection_tests/package.xml @@ -29,6 +29,7 @@ rosidl_typesupport_introspection_cpp rosidl_typesupport_interface test_interface_files + service_msgs ament_cmake