diff --git a/rmw/include/rmw/dynamic_message_type_support.h b/rmw/include/rmw/dynamic_message_type_support.h index ea9e78fb..3b84d391 100644 --- a/rmw/include/rmw/dynamic_message_type_support.h +++ b/rmw/include/rmw/dynamic_message_type_support.h @@ -36,7 +36,50 @@ extern "C" /// Interfaces for runtime interface reflection // RUNTIME INTERFACE REFLECTION TYPE SUPPORT ======================================================= -/// Get dynamic type message typesupport with bound message description +/// Initialize dynamic type message typesupport, binding message description +/** + * NOTE: Take note of the ownership rules for the returned struct and the `description` argument! + * + * If the user passes a NULL description, it is deferred instead, the middleware is responsibile + * for populating the fields on type discovery!!! + * + * Ownership: + * - The `rosidl_message_type_support_t *` returned from this function has different ownership + * rules compared to the statically allocated `rosidl_message_type_support_t` structs from + * code-generated types! + * - The caller is responsible for deallocating the returned pointer + * + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | Yes + * Thread-Safe | No + * Uses Atomics | No + * Lock-Free | Yes + */ +RMW_PUBLIC +RMW_WARN_UNUSED +rmw_ret_t +rmw_dynamic_message_type_support_handle_init( + rosidl_dynamic_typesupport_serialization_support_t * serialization_support, + bool middleware_supports_type_discovery, + const rosidl_type_hash_t * type_hash, + const rosidl_runtime_c__type_description__TypeDescription * type_description, + const rosidl_runtime_c__type_description__TypeSource__Sequence * type_description_sources, + rcutils_allocator_t * allocator, + rosidl_message_type_support_t * ts); // OUT + +/// Finalize a rosidl_message_type_support_t obtained with +/// `rmw_dynamic_message_type_support_handle_create()`, which has dynamically allocated members +/// +/// NOTE: Using this on a statically allocated typesupport will cause undefined behavior! +/// (Static memory will get freed in that case.) +RMW_PUBLIC +RMW_WARN_UNUSED +rmw_ret_t +rmw_dynamic_message_type_support_handle_fini(rosidl_message_type_support_t * ts); + +/// Create dynamic type message typesupport with bound message description /** * NOTE: Take note of the ownership rules for the returned struct and the `description` argument! * @@ -66,6 +109,7 @@ rmw_dynamic_message_type_support_handle_create( const rosidl_type_hash_t * type_hash, const rosidl_runtime_c__type_description__TypeDescription * type_description, const rosidl_runtime_c__type_description__TypeSource__Sequence * type_description_sources, + rcutils_allocator_t * allocator, rosidl_message_type_support_t ** ts); // OUT /// Destroy a rosidl_message_type_support_t obtained with diff --git a/rmw/src/dynamic_message_type_support.c b/rmw/src/dynamic_message_type_support.c index 6bb24949..8a5b2e8b 100644 --- a/rmw/src/dynamic_message_type_support.c +++ b/rmw/src/dynamic_message_type_support.c @@ -33,8 +33,52 @@ extern "C" // NOTE(methylDragon): How do we test this? It depends on specific serialization support. Do I just // use the FastRTPS support then? +rmw_ret_t +rmw_dynamic_message_type_support_handle_init( + rosidl_dynamic_typesupport_serialization_support_t * serialization_support, + bool middleware_supports_type_discovery, + const rosidl_type_hash_t * type_hash, + const rosidl_runtime_c__type_description__TypeDescription * type_description, + const rosidl_runtime_c__type_description__TypeSource__Sequence * type_description_sources, + rcutils_allocator_t * allocator, + rosidl_message_type_support_t * ts) +{ + if (!middleware_supports_type_discovery && type_description == NULL) { + RMW_SET_ERROR_MSG( + "Middleware does not support type discovery. Deferred dynamic type message type support will " + "never be populated. You must provide a type description."); + return RMW_RET_INVALID_ARGUMENT; + } + // TODO(methylDragon): Remove if and when the deferred description path is supported + if (type_description == NULL) { + RMW_SET_ERROR_MSG( + "Deferred type description is not currently supported. You must provide a type description."); + return RMW_RET_INVALID_ARGUMENT; + } + + RMW_CHECK_ARGUMENT_FOR_NULL(serialization_support, RMW_RET_INVALID_ARGUMENT); + RMW_CHECK_ARGUMENT_FOR_NULL(type_hash, RMW_RET_INVALID_ARGUMENT); + RMW_CHECK_ARGUMENT_FOR_NULL(type_description, RMW_RET_INVALID_ARGUMENT); + RMW_CHECK_ARGUMENT_FOR_NULL(allocator, RMW_RET_INVALID_ARGUMENT); + RMW_CHECK_ARGUMENT_FOR_NULL(ts, RMW_RET_INVALID_ARGUMENT); + + // NOTE(methylDragon): Not supported for now + // RMW_CHECK_ARGUMENT_FOR_NULL(type_description_sources, RMW_RET_INVALID_ARGUMENT); + + return rmw_convert_rcutils_ret_to_rmw_ret( + rosidl_dynamic_message_type_support_handle_init( + serialization_support, type_hash, type_description, type_description_sources, allocator, ts)); +} + +rmw_ret_t +rmw_dynamic_message_type_support_handle_fini(rosidl_message_type_support_t * ts) +{ + if (!ts) { + return RCUTILS_RET_OK; + } + return rmw_convert_rcutils_ret_to_rmw_ret(rosidl_dynamic_message_type_support_handle_fini(ts)); +} -/// Create a rosidl_message_type_support_t from a TypeDescription message rmw_ret_t rmw_dynamic_message_type_support_handle_create( rosidl_dynamic_typesupport_serialization_support_t * serialization_support, @@ -42,6 +86,7 @@ rmw_dynamic_message_type_support_handle_create( const rosidl_type_hash_t * type_hash, const rosidl_runtime_c__type_description__TypeDescription * type_description, const rosidl_runtime_c__type_description__TypeSource__Sequence * type_description_sources, + rcutils_allocator_t * allocator, rosidl_message_type_support_t ** ts) { if (!middleware_supports_type_discovery && type_description == NULL) { @@ -60,6 +105,7 @@ rmw_dynamic_message_type_support_handle_create( RMW_CHECK_ARGUMENT_FOR_NULL(serialization_support, RMW_RET_INVALID_ARGUMENT); RMW_CHECK_ARGUMENT_FOR_NULL(type_hash, RMW_RET_INVALID_ARGUMENT); RMW_CHECK_ARGUMENT_FOR_NULL(type_description, RMW_RET_INVALID_ARGUMENT); + RMW_CHECK_ARGUMENT_FOR_NULL(allocator, RMW_RET_INVALID_ARGUMENT); RMW_CHECK_ARGUMENT_FOR_NULL(ts, RMW_RET_INVALID_ARGUMENT); // NOTE(methylDragon): Not supported for now @@ -67,13 +113,15 @@ rmw_dynamic_message_type_support_handle_create( return rmw_convert_rcutils_ret_to_rmw_ret( rosidl_dynamic_message_type_support_handle_create( - serialization_support, type_hash, type_description, type_description_sources, ts)); + serialization_support, type_hash, type_description, type_description_sources, allocator, ts)); } rmw_ret_t rmw_dynamic_message_type_support_handle_destroy(rosidl_message_type_support_t * ts) { - RCUTILS_CHECK_ARGUMENT_FOR_NULL(ts, RMW_RET_INVALID_ARGUMENT); + if (!ts) { + return RCUTILS_RET_OK; + } return rmw_convert_rcutils_ret_to_rmw_ret(rosidl_dynamic_message_type_support_handle_destroy(ts)); }