ROS 2 rclcpp + rcl - jazzy  jazzy
ROS 2 C++ Client Library with ROS Client Library
dynamic_message_type_support.c
1 // Copyright 2022 Open Source Robotics Foundation, Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifdef __cplusplus
16 extern "C"
17 {
18 #endif
19 
20 #include <rcutils/logging_macros.h>
21 #include <rosidl_runtime_c/message_type_support_struct.h>
22 #include <rosidl_runtime_c/type_description/type_description__struct.h>
23 
24 #include "rmw/dynamic_message_type_support.h"
25 
26 #include "rcl/allocator.h"
27 #include "rcl/common.h"
28 #include "rcl/error_handling.h"
29 #include "rcl/dynamic_message_type_support.h"
30 #include "rcl/type_hash.h"
31 #include "rcl/types.h"
32 
33 
35 RCL_PUBLIC
36 RCL_WARN_UNUSED
38 rcl_dynamic_message_type_support_handle_init(
39  const char * serialization_lib_name,
40  const rosidl_runtime_c__type_description__TypeDescription * description,
41  rcl_allocator_t * allocator,
42  rosidl_message_type_support_t * ts)
43 {
44  RCUTILS_CHECK_ARGUMENT_FOR_NULL(ts, RCUTILS_RET_INVALID_ARGUMENT);
45  RCUTILS_CHECK_ARGUMENT_FOR_NULL(allocator, RCUTILS_RET_INVALID_ARGUMENT);
46  if (!rcutils_allocator_is_valid(allocator)) {
47  RCUTILS_SET_ERROR_MSG("allocator is invalid");
48  return RCUTILS_RET_INVALID_ARGUMENT;
49  }
50 
51  // TODO(methylDragon): Remove if and when the deferred description path is supported
52  if (description == NULL) {
53  RCUTILS_SET_ERROR_MSG(
54  "Deferred type description is not currently supported. You must provide a type description.");
55  return RCUTILS_RET_INVALID_ARGUMENT;
56  }
57 
58  bool middleware_supports_type_discovery = rmw_feature_supported(
59  RMW_MIDDLEWARE_SUPPORTS_TYPE_DISCOVERY);
60  if (!middleware_supports_type_discovery && description == NULL) {
61  RCL_SET_ERROR_MSG(
62  "Middleware does not support type discovery. Deferred dynamic type message type support will "
63  "never be populated. You must provide a type description.");
64  return RCUTILS_RET_INVALID_ARGUMENT;
65  }
66  // TODO(methylDragon): Remove if and when the deferred description path is supported
67  if (description == NULL) {
68  RCL_SET_ERROR_MSG(
69  "Deferred type description is not currently supported. You must provide a type description.");
70  return RCUTILS_RET_INVALID_ARGUMENT;
71  }
72 
73  rosidl_dynamic_typesupport_serialization_support_t serialization_support;
74  rcl_ret_t ret = rcl_convert_rmw_ret_to_rcl_ret(
75  rmw_serialization_support_init(serialization_lib_name, allocator, &serialization_support));
76  if (ret != RCL_RET_OK) {
77  RCL_SET_ERROR_MSG("failed to get serialization support");
78  if (ret == RCL_RET_OK) { // It means serialization support was NULL
79  return RCL_RET_ERROR;
80  } else {
81  return ret;
82  }
83  }
84 
85  rosidl_type_hash_t type_hash;
86  ret = rcl_calculate_type_hash(
87  // TODO(methylDragon): Replace this cast with the conversion function when it is ready
88  // Either a custom function, or from https://github.com/ros2/rcl/pull/1052
89  (const type_description_interfaces__msg__TypeDescription *) description, &type_hash);
90  if (ret != RCL_RET_OK) {
91  RCL_SET_ERROR_MSG("failed to get type hash");
92  return ret;
93  }
94 
95  ret = rcl_convert_rcutils_ret_to_rcl_ret(
96  rosidl_dynamic_message_type_support_handle_init(
97  &serialization_support,
98  &type_hash, // type_hash
99  description, // type_description
100  NULL, // type_description_sources
101  allocator,
102  ts
103  )
104  );
105  if (ret != RCL_RET_OK) {
106  rcutils_error_string_t error_string = rcutils_get_error_string();
107  rcutils_reset_error();
108  RCL_SET_ERROR_MSG_WITH_FORMAT_STRING(
109  "failed to init rosidl_message_type_support:\n%s", error_string.str);
110  return ret;
111  }
112 
113  return RCL_RET_OK;
114 }
115 
116 RCL_PUBLIC
117 RCL_WARN_UNUSED
118 rcl_ret_t
119 rcl_dynamic_message_type_support_handle_fini(rosidl_message_type_support_t * ts)
120 {
121  RCL_CHECK_ARGUMENT_FOR_NULL(ts, RCL_RET_INVALID_ARGUMENT);
122  return rcl_convert_rcutils_ret_to_rcl_ret(rosidl_dynamic_message_type_support_handle_fini(ts));
123 }
124 
125 #ifdef __cplusplus
126 }
127 #endif
rcutils_allocator_t rcl_allocator_t
Encapsulation of an allocator.
Definition: allocator.h:31
#define RCL_RET_OK
Success return code.
Definition: types.h:27
#define RCL_RET_INVALID_ARGUMENT
Invalid argument return code.
Definition: types.h:35
#define RCL_RET_ERROR
Unspecified error return code.
Definition: types.h:29
rmw_ret_t rcl_ret_t
The type that holds an rcl return code.
Definition: types.h:24