From bd9788a948891315c5f6de7a9508d8c31ad3359e Mon Sep 17 00:00:00 2001 From: methylDragon Date: Mon, 20 Mar 2023 15:50:38 -0700 Subject: [PATCH 1/5] Implement dynamic typesupport wrappers Signed-off-by: methylDragon --- rclcpp/CMakeLists.txt | 6 + .../detail/dynamic_data_impl.hpp | 326 +++++++++ .../detail/dynamic_type_builder_impl.hpp | 162 +++++ .../dynamic_typesupport/dynamic_data.hpp | 373 ++++++++++ .../dynamic_typesupport/dynamic_message.hpp | 105 +++ .../dynamic_message_type.hpp | 93 +++ .../dynamic_serialization_support.hpp | 110 +++ .../dynamic_typesupport/dynamic_type.hpp | 196 ++++++ .../dynamic_type_builder.hpp | 318 +++++++++ rclcpp/include/rclcpp/rclcpp.hpp | 13 + rclcpp/package.xml | 1 + .../dynamic_typesupport/dynamic_data.cpp | 642 ++++++++++++++++++ .../dynamic_typesupport/dynamic_message.cpp | 61 ++ .../dynamic_message_type.cpp | 57 ++ .../dynamic_serialization_support.cpp | 131 ++++ .../dynamic_typesupport/dynamic_type.cpp | 320 +++++++++ .../dynamic_type_builder.cpp | 492 ++++++++++++++ 17 files changed, 3406 insertions(+) create mode 100644 rclcpp/include/rclcpp/dynamic_typesupport/detail/dynamic_data_impl.hpp create mode 100644 rclcpp/include/rclcpp/dynamic_typesupport/detail/dynamic_type_builder_impl.hpp create mode 100644 rclcpp/include/rclcpp/dynamic_typesupport/dynamic_data.hpp create mode 100644 rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message.hpp create mode 100644 rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message_type.hpp create mode 100644 rclcpp/include/rclcpp/dynamic_typesupport/dynamic_serialization_support.hpp create mode 100644 rclcpp/include/rclcpp/dynamic_typesupport/dynamic_type.hpp create mode 100644 rclcpp/include/rclcpp/dynamic_typesupport/dynamic_type_builder.hpp create mode 100644 rclcpp/src/rclcpp/dynamic_typesupport/dynamic_data.cpp create mode 100644 rclcpp/src/rclcpp/dynamic_typesupport/dynamic_message.cpp create mode 100644 rclcpp/src/rclcpp/dynamic_typesupport/dynamic_message_type.cpp create mode 100644 rclcpp/src/rclcpp/dynamic_typesupport/dynamic_serialization_support.cpp create mode 100644 rclcpp/src/rclcpp/dynamic_typesupport/dynamic_type.cpp create mode 100644 rclcpp/src/rclcpp/dynamic_typesupport/dynamic_type_builder.cpp diff --git a/rclcpp/CMakeLists.txt b/rclcpp/CMakeLists.txt index 6979d980f8..583aeece44 100644 --- a/rclcpp/CMakeLists.txt +++ b/rclcpp/CMakeLists.txt @@ -49,6 +49,12 @@ set(${PROJECT_NAME}_SRCS src/rclcpp/detail/rmw_implementation_specific_subscription_payload.cpp src/rclcpp/detail/utilities.cpp src/rclcpp/duration.cpp + src/rclcpp/dynamic_typesupport/dynamic_data.cpp + src/rclcpp/dynamic_typesupport/dynamic_message.cpp + src/rclcpp/dynamic_typesupport/dynamic_message_type.cpp + src/rclcpp/dynamic_typesupport/dynamic_serialization_support.cpp + src/rclcpp/dynamic_typesupport/dynamic_type.cpp + src/rclcpp/dynamic_typesupport/dynamic_type_builder.cpp src/rclcpp/event.cpp src/rclcpp/exceptions/exceptions.cpp src/rclcpp/executable_list.cpp diff --git a/rclcpp/include/rclcpp/dynamic_typesupport/detail/dynamic_data_impl.hpp b/rclcpp/include/rclcpp/dynamic_typesupport/detail/dynamic_data_impl.hpp new file mode 100644 index 0000000000..d2e77247ae --- /dev/null +++ b/rclcpp/include/rclcpp/dynamic_typesupport/detail/dynamic_data_impl.hpp @@ -0,0 +1,326 @@ +// Copyright 2023 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef RCLCPP__DYNAMIC_TYPESUPPORT__DETAIL__DYNAMIC_DATA_IMPL_HPP_ +#define RCLCPP__DYNAMIC_TYPESUPPORT__DETAIL__DYNAMIC_DATA_IMPL_HPP_ + +#include +#include +#include +#include + +#include +#include +#include "rclcpp/exceptions.hpp" + +#ifndef RCLCPP__DYNAMIC_TYPESUPPORT__DYNAMIC_DATA_HPP_ +#include "rclcpp/dynamic_typesupport/dynamic_data.hpp" +#endif + + +#define __DYNAMIC_DATA_GET_VALUE_BY_ID_FN(ValueT, FunctionT) \ + template<> \ + ValueT \ + DynamicData::get_value(rosidl_dynamic_typesupport_member_id_t id) \ + { \ + ValueT out; \ + rosidl_dynamic_typesupport_dynamic_data_get_ ## FunctionT ## _value( \ + rosidl_dynamic_data_.get(), id, &out); \ + return out; \ + } + +#define __DYNAMIC_DATA_GET_VALUE_BY_NAME_FN(ValueT, FunctionT) \ + template<> \ + ValueT \ + DynamicData::get_value(const std::string & name) \ + { \ + return get_value(get_member_id(name)); \ + } + +#define __DYNAMIC_DATA_SET_VALUE_BY_ID_FN(ValueT, FunctionT) \ + template<> \ + void \ + DynamicData::set_value(rosidl_dynamic_typesupport_member_id_t id, ValueT value) \ + { \ + rosidl_dynamic_typesupport_dynamic_data_set_ ## FunctionT ## _value( \ + rosidl_dynamic_data_.get(), id, value); \ + } + +#define __DYNAMIC_DATA_SET_VALUE_BY_NAME_FN(ValueT, FunctionT) \ + template<> \ + void \ + DynamicData::set_value(const std::string & name, ValueT value) \ + { \ + set_value(get_member_id(name), value); \ + } + +#define __DYNAMIC_DATA_INSERT_VALUE(ValueT, FunctionT) \ + template<> \ + rosidl_dynamic_typesupport_member_id_t \ + DynamicData::insert_value(ValueT value) \ + { \ + rosidl_dynamic_typesupport_member_id_t out; \ + rosidl_dynamic_typesupport_dynamic_data_insert_ ## FunctionT ## _value( \ + rosidl_dynamic_data_.get(), value, &out); \ + return out; \ + } + +#define DYNAMIC_DATA_DEFINITIONS(ValueT, FunctionT) \ + __DYNAMIC_DATA_GET_VALUE_BY_ID_FN(ValueT, FunctionT) \ + __DYNAMIC_DATA_GET_VALUE_BY_NAME_FN(ValueT, FunctionT) \ + __DYNAMIC_DATA_SET_VALUE_BY_ID_FN(ValueT, FunctionT) \ + __DYNAMIC_DATA_SET_VALUE_BY_NAME_FN(ValueT, FunctionT) \ + __DYNAMIC_DATA_INSERT_VALUE(ValueT, FunctionT) + + +namespace rclcpp +{ +namespace dynamic_typesupport +{ + +/** + * Since we're in a ROS layer, these should support all ROS interface C++ types as found in: + * https://docs.ros.org/en/rolling/Concepts/About-ROS-Interfaces.html + * + * Explicitly: + * - Basic types: bool, byte, char + * - Float types: float, double + * - Int types: int8_t, int16_t, int32_t, int64_t + * - Unsigned int types: uint8_t, uint16_t, uint32_t, uint64_t + * - String types: std::string, std::u16string + */ + +DYNAMIC_DATA_DEFINITIONS(bool, bool); +// DYNAMIC_DATA_DEFINITIONS(std::byte, byte); +DYNAMIC_DATA_DEFINITIONS(char, char); +DYNAMIC_DATA_DEFINITIONS(float, float32); +DYNAMIC_DATA_DEFINITIONS(double, float64); +DYNAMIC_DATA_DEFINITIONS(int8_t, int8); +DYNAMIC_DATA_DEFINITIONS(int16_t, int16); +DYNAMIC_DATA_DEFINITIONS(int32_t, int32); +DYNAMIC_DATA_DEFINITIONS(int64_t, int64); +DYNAMIC_DATA_DEFINITIONS(uint8_t, uint8); +DYNAMIC_DATA_DEFINITIONS(uint16_t, uint16); +DYNAMIC_DATA_DEFINITIONS(uint32_t, uint32); +DYNAMIC_DATA_DEFINITIONS(uint64_t, uint64); +// DYNAMIC_DATA_DEFINITIONS(std::string, std::string); +// DYNAMIC_DATA_DEFINITIONS(std::u16string, std::u16string); + +// Byte and String getters have a different implementation and are defined below + + +// BYTE ============================================================================================ +template<> +std::byte +DynamicData::get_value(rosidl_dynamic_typesupport_member_id_t id) +{ + unsigned char out; + rosidl_dynamic_typesupport_dynamic_data_get_byte_value(get_rosidl_dynamic_data(), id, &out); + return static_cast(out); +} + + +template<> +std::byte +DynamicData::get_value(const std::string & name) +{ + return get_value(get_member_id(name)); +} + + +template<> +void +DynamicData::set_value( + rosidl_dynamic_typesupport_member_id_t id, const std::byte value) +{ + rosidl_dynamic_typesupport_dynamic_data_set_byte_value( + rosidl_dynamic_data_.get(), id, static_cast(value)); +} + + +template<> +void +DynamicData::set_value(const std::string & name, const std::byte value) +{ + set_value(get_member_id(name), value); +} + + +template<> +rosidl_dynamic_typesupport_member_id_t +DynamicData::insert_value(const std::byte value) +{ + rosidl_dynamic_typesupport_member_id_t out; + rosidl_dynamic_typesupport_dynamic_data_insert_byte_value( + rosidl_dynamic_data_.get(), static_cast(value), &out); + return out; +} + + +// STRINGS ========================================================================================= +template<> +std::string +DynamicData::get_value(rosidl_dynamic_typesupport_member_id_t id) +{ + size_t buf_length; + char * buf = nullptr; + rosidl_dynamic_typesupport_dynamic_data_get_string_value( + get_rosidl_dynamic_data(), id, &buf, &buf_length); + auto out = std::string(buf, buf_length); + free(buf); + return out; +} + + +template<> +std::u16string +DynamicData::get_value(rosidl_dynamic_typesupport_member_id_t id) +{ + size_t buf_length; + char16_t * buf = nullptr; + rosidl_dynamic_typesupport_dynamic_data_get_wstring_value( + get_rosidl_dynamic_data(), id, &buf, &buf_length); + auto out = std::u16string(buf, buf_length); + free(buf); + return out; +} + + +template<> +std::string +DynamicData::get_value(const std::string & name) +{ + return get_value(get_member_id(name)); +} + + +template<> +std::u16string +DynamicData::get_value(const std::string & name) +{ + return get_value(get_member_id(name)); +} + + +template<> +void +DynamicData::set_value( + rosidl_dynamic_typesupport_member_id_t id, const std::string value) +{ + rosidl_dynamic_typesupport_dynamic_data_set_string_value( + rosidl_dynamic_data_.get(), id, value.c_str(), value.size()); +} + + +template<> +void +DynamicData::set_value( + rosidl_dynamic_typesupport_member_id_t id, const std::u16string value) +{ + rosidl_dynamic_typesupport_dynamic_data_set_wstring_value( + rosidl_dynamic_data_.get(), id, value.c_str(), value.size()); +} + + +template<> +void +DynamicData::set_value(const std::string & name, const std::string value) +{ + set_value(get_member_id(name), value); +} + + +template<> +void +DynamicData::set_value(const std::string & name, const std::u16string value) +{ + set_value(get_member_id(name), value); +} + + +template<> +rosidl_dynamic_typesupport_member_id_t +DynamicData::insert_value(const std::string value) +{ + rosidl_dynamic_typesupport_member_id_t out; + rosidl_dynamic_typesupport_dynamic_data_insert_string_value( + rosidl_dynamic_data_.get(), value.c_str(), value.size(), &out); + return out; +} + + +template<> +rosidl_dynamic_typesupport_member_id_t +DynamicData::insert_value(const std::u16string value) +{ + rosidl_dynamic_typesupport_member_id_t out; + rosidl_dynamic_typesupport_dynamic_data_insert_wstring_value( + rosidl_dynamic_data_.get(), value.c_str(), value.size(), &out); + return out; +} + + +// THROW FOR UNSUPPORTED TYPES ===================================================================== +template +ValueT +DynamicData::get_value(rosidl_dynamic_typesupport_member_id_t id) +{ + throw rclcpp::exceptions::UnimplementedError("get_value is not implemented for input type"); +} + + +template +ValueT +DynamicData::get_value(const std::string & name) +{ + throw rclcpp::exceptions::UnimplementedError("get_value is not implemented for input type"); +} + + +template +void +DynamicData::set_value( + rosidl_dynamic_typesupport_member_id_t id, ValueT value) +{ + throw rclcpp::exceptions::UnimplementedError("set_value is not implemented for input type"); +} + + +template +void +DynamicData::set_value(const std::string & name, ValueT value) +{ + throw rclcpp::exceptions::UnimplementedError("set_value is not implemented for input type"); +} + + +template +rosidl_dynamic_typesupport_member_id_t +DynamicData::insert_value(ValueT value) +{ + throw rclcpp::exceptions::UnimplementedError("insert_value is not implemented for input type"); +} + + +} // namespace dynamic_typesupport +} // namespace rclcpp + +#undef __DYNAMIC_DATA_GET_VALUE_BY_ID_FN +#undef __DYNAMIC_DATA_GET_VALUE_BY_NAME_FN +#undef __DYNAMIC_DATA_SET_VALUE_BY_ID_FN +#undef __DYNAMIC_DATA_SET_VALUE_BY_NAME_FN +#undef __DYNAMIC_DATA_INSERT_VALUE +#undef DYNAMIC_DATA_DEFINITIONS + +#endif // RCLCPP__DYNAMIC_TYPESUPPORT__DETAIL__DYNAMIC_DATA_IMPL_HPP_ diff --git a/rclcpp/include/rclcpp/dynamic_typesupport/detail/dynamic_type_builder_impl.hpp b/rclcpp/include/rclcpp/dynamic_typesupport/detail/dynamic_type_builder_impl.hpp new file mode 100644 index 0000000000..e71d4702bd --- /dev/null +++ b/rclcpp/include/rclcpp/dynamic_typesupport/detail/dynamic_type_builder_impl.hpp @@ -0,0 +1,162 @@ +// Copyright 2023 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef RCLCPP__DYNAMIC_TYPESUPPORT__DETAIL__DYNAMIC_TYPE_BUILDER_IMPL_HPP_ +#define RCLCPP__DYNAMIC_TYPESUPPORT__DETAIL__DYNAMIC_TYPE_BUILDER_IMPL_HPP_ + +#include +#include +#include +#include + +#include +#include +#include "rclcpp/exceptions.hpp" + +#ifndef RCLCPP__DYNAMIC_TYPESUPPORT__DYNAMIC_TYPE_BUILDER_HPP_ +#include "rclcpp/dynamic_typesupport/dynamic_type_builder.hpp" +#endif + + +#define __DYNAMIC_TYPE_BUILDER_ADD_MEMBER_FN(MemberT, FunctionT) \ + template<> \ + void \ + DynamicTypeBuilder::add_member( \ + rosidl_dynamic_typesupport_member_id_t id, const std::string & name) \ + { \ + rosidl_dynamic_typesupport_dynamic_type_builder_add_ ## FunctionT ## _member( \ + rosidl_dynamic_type_builder_.get(), id, name.c_str(), name.size()); \ + } + +#define __DYNAMIC_TYPE_BUILDER_ADD_ARRAY_MEMBER_FN(MemberT, FunctionT) \ + template<> \ + void \ + DynamicTypeBuilder::add_array_member( \ + rosidl_dynamic_typesupport_member_id_t id, const std::string & name, size_t array_length) \ + { \ + rosidl_dynamic_typesupport_dynamic_type_builder_add_ ## FunctionT ## _array_member( \ + rosidl_dynamic_type_builder_.get(), id, name.c_str(), name.size(), array_length); \ + } + +#define __DYNAMIC_TYPE_BUILDER_ADD_UNBOUNDED_SEQUENCE_MEMBER_FN(MemberT, FunctionT) \ + template<> \ + void \ + DynamicTypeBuilder::add_unbounded_sequence_member( \ + rosidl_dynamic_typesupport_member_id_t id, const std::string & name) \ + { \ + rosidl_dynamic_typesupport_dynamic_type_builder_add_ ## FunctionT ## _unbounded_sequence_member( \ + rosidl_dynamic_type_builder_.get(), id, name.c_str(), name.size()); \ + } + +#define __DYNAMIC_TYPE_BUILDER_ADD_BOUNDED_SEQUENCE_MEMBER_FN(MemberT, FunctionT) \ + template<> \ + void \ + DynamicTypeBuilder::add_bounded_sequence_member( \ + rosidl_dynamic_typesupport_member_id_t id, const std::string & name, size_t sequence_bound) \ + { \ + rosidl_dynamic_typesupport_dynamic_type_builder_add_ ## FunctionT ## _bounded_sequence_member( \ + rosidl_dynamic_type_builder_.get(), id, name.c_str(), name.size(), sequence_bound); \ + } + +#define DYNAMIC_TYPE_BUILDER_DEFINITIONS(MemberT, FunctionT) \ + __DYNAMIC_TYPE_BUILDER_ADD_MEMBER_FN(MemberT, FunctionT) \ + __DYNAMIC_TYPE_BUILDER_ADD_ARRAY_MEMBER_FN(MemberT, FunctionT) \ + __DYNAMIC_TYPE_BUILDER_ADD_UNBOUNDED_SEQUENCE_MEMBER_FN(MemberT, FunctionT) \ + __DYNAMIC_TYPE_BUILDER_ADD_BOUNDED_SEQUENCE_MEMBER_FN(MemberT, FunctionT) \ + + +namespace rclcpp +{ +namespace dynamic_typesupport +{ + +/** + * Since we're in a ROS layer, these should support all ROS interface C++ types as found in: + * https://docs.ros.org/en/rolling/Concepts/About-ROS-Interfaces.html + * + * Explicitly: + * - Basic types: bool, byte, char + * - Float types: float, double + * - Int types: int8_t, int16_t, int32_t, int64_t + * - Unsigned int types: uint8_t, uint16_t, uint32_t, uint64_t + * - String types: std::string, std::u16string + */ + +DYNAMIC_TYPE_BUILDER_DEFINITIONS(bool, bool); +DYNAMIC_TYPE_BUILDER_DEFINITIONS(std::byte, byte); +DYNAMIC_TYPE_BUILDER_DEFINITIONS(char, char); +DYNAMIC_TYPE_BUILDER_DEFINITIONS(float, float32); +DYNAMIC_TYPE_BUILDER_DEFINITIONS(double, float64); +DYNAMIC_TYPE_BUILDER_DEFINITIONS(int8_t, int8); +DYNAMIC_TYPE_BUILDER_DEFINITIONS(int16_t, int16); +DYNAMIC_TYPE_BUILDER_DEFINITIONS(int32_t, int32); +DYNAMIC_TYPE_BUILDER_DEFINITIONS(int64_t, int64); +DYNAMIC_TYPE_BUILDER_DEFINITIONS(uint8_t, uint8); +DYNAMIC_TYPE_BUILDER_DEFINITIONS(uint16_t, uint16); +DYNAMIC_TYPE_BUILDER_DEFINITIONS(uint32_t, uint32); +DYNAMIC_TYPE_BUILDER_DEFINITIONS(uint64_t, uint64); +DYNAMIC_TYPE_BUILDER_DEFINITIONS(std::string, string); +DYNAMIC_TYPE_BUILDER_DEFINITIONS(std::u16string, wstring); + + +// THROW FOR UNSUPPORTED TYPES ===================================================================== +template +void +DynamicTypeBuilder::add_member(rosidl_dynamic_typesupport_member_id_t id, const std::string & name) +{ + throw rclcpp::exceptions::UnimplementedError( + "add_member is not implemented for input type"); +} + + +template +void +DynamicTypeBuilder::add_array_member( + rosidl_dynamic_typesupport_member_id_t id, const std::string & name, size_t array_length) +{ + throw rclcpp::exceptions::UnimplementedError( + "add_array_member is not implemented for input type"); +} + + +template +void +DynamicTypeBuilder::add_unbounded_sequence_member( + rosidl_dynamic_typesupport_member_id_t id, const std::string & name) +{ + throw rclcpp::exceptions::UnimplementedError( + "add_unbounded_sequence_member is not implemented for input type"); +} + + +template +void +DynamicTypeBuilder::add_bounded_sequence_member( + rosidl_dynamic_typesupport_member_id_t id, const std::string & name, size_t sequence_bound) +{ + throw rclcpp::exceptions::UnimplementedError( + "add_bounded_sequence_member is not implemented for input type"); +} + + +} // namespace dynamic_typesupport +} // namespace rclcpp + +#undef __DYNAMIC_TYPE_BUILDER_ADD_MEMBER_FN +#undef __DYNAMIC_TYPE_BUILDER_ADD_ARRAY_MEMBER_FN +#undef __DYNAMIC_TYPE_BUILDER_ADD_UNBOUNDED_SEQUENCE_MEMBER_FN +#undef __DYNAMIC_TYPE_BUILDER_ADD_BOUNDED_SEQUENCE_MEMBER_FN +#undef DYNAMIC_TYPE_BUILDER_DEFINITIONS + +#endif // RCLCPP__DYNAMIC_TYPESUPPORT__DETAIL__DYNAMIC_TYPE_BUILDER_IMPL_HPP_ diff --git a/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_data.hpp b/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_data.hpp new file mode 100644 index 0000000000..9429cac90f --- /dev/null +++ b/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_data.hpp @@ -0,0 +1,373 @@ +// Copyright 2023 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef RCLCPP__DYNAMIC_TYPESUPPORT__DYNAMIC_DATA_HPP_ +#define RCLCPP__DYNAMIC_TYPESUPPORT__DYNAMIC_DATA_HPP_ + + +#include +#include + +#include "rclcpp/dynamic_typesupport/dynamic_serialization_support.hpp" +#include "rclcpp/macros.hpp" +#include "rclcpp/visibility_control.hpp" + +#include + + +namespace rclcpp +{ +namespace dynamic_typesupport +{ + + +class DynamicType; +class DynamicTypeBuilder; + +/// Utility wrapper class for rosidl_dynamic_typesupport_dynamic_data_t * +/** + * This class: + * - Manages the lifetime of the raw pointer. + * - Exposes getter methods to get the raw pointer and shared pointers + * - Exposes the underlying serialization support API + * + * Ownership: + * - This class borrows the rosidl_dynamic_typesupport_serialization_support_t stored in the passed + * DynamicSerializationSupport. So it cannot outlive the DynamicSerializationSupport. + * - The DynamicSerializationSupport's rosidl_dynamic_typesupport_serialization_support_t pointer + * must point to the same location in memory as the stored raw pointer! + */ +class DynamicData : public std::enable_shared_from_this +{ +public: + RCLCPP_SMART_PTR_ALIASES_ONLY(DynamicData) + + // CONSTRUCTION ================================================================================== + // Most constructors require a passed in DynamicSerializationSupport::SharedPtr, to extend the + // lifetime of the serialization support (if the constructor cannot otherwise get it from args). + // + // In cases where a dynamic data pointer is passed, the serialization support composed by + // the data should be the exact same object managed by the DynamicSerializationSupport, + // otherwise the lifetime management will not work properly. + + /// Construct a new DynamicData with the provided dynamic type builder + RCLCPP_PUBLIC + explicit DynamicData(std::shared_ptr dynamic_type_builder); + + /// Construct a new DynamicData with the provided dynamic type + RCLCPP_PUBLIC + explicit DynamicData(std::shared_ptr dynamic_type); + + /// Assume ownership of raw pointer + RCLCPP_PUBLIC + DynamicData( + DynamicSerializationSupport::SharedPtr serialization_support, + rosidl_dynamic_typesupport_dynamic_data_t * rosidl_dynamic_data); + + /// Copy shared pointer + RCLCPP_PUBLIC + DynamicData( + DynamicSerializationSupport::SharedPtr serialization_support, + std::shared_ptr rosidl_dynamic_data); + + /// Loaning constructor + /// Must only be called with raw ptr obtained from loaning! + // NOTE(methylDragon): I'd put this in protected, but I need this exposed to + // enable_shared_from_this... + RCLCPP_PUBLIC + DynamicData( + DynamicData::SharedPtr parent_data, + rosidl_dynamic_typesupport_dynamic_data_t * rosidl_loaned_data); + + // NOTE(methylDragon): Deliberately no constructor from description to nudge users towards using + // construction from dynamic type/builder, which is more efficient + + /// Copy constructor + RCLCPP_PUBLIC + DynamicData(const DynamicData & other); + + /// Move constructor + RCLCPP_PUBLIC + DynamicData(DynamicData && other) noexcept; + + /// Copy assignment + RCLCPP_PUBLIC + DynamicData & operator=(const DynamicData & other); + + /// Move assignment + RCLCPP_PUBLIC + DynamicData & operator=(DynamicData && other) noexcept; + + RCLCPP_PUBLIC + virtual ~DynamicData(); + + + // GETTERS ======================================================================================= + RCLCPP_PUBLIC + const std::string + get_library_identifier() const; + + RCLCPP_PUBLIC + const std::string + get_name() const; + + RCLCPP_PUBLIC + rosidl_dynamic_typesupport_dynamic_data_t * + get_rosidl_dynamic_data(); + + RCLCPP_PUBLIC + const rosidl_dynamic_typesupport_dynamic_data_t * + get_rosidl_dynamic_data() const; + + RCLCPP_PUBLIC + std::shared_ptr + get_shared_rosidl_dynamic_data(); + + RCLCPP_PUBLIC + std::shared_ptr + get_shared_rosidl_dynamic_data() const; + + RCLCPP_PUBLIC + DynamicSerializationSupport::SharedPtr + get_shared_dynamic_serialization_support(); + + RCLCPP_PUBLIC + std::shared_ptr + get_shared_dynamic_serialization_support() const; + + RCLCPP_PUBLIC + size_t + get_item_count() const; + + RCLCPP_PUBLIC + rosidl_dynamic_typesupport_member_id_t + get_member_id(size_t index) const; + + RCLCPP_PUBLIC + rosidl_dynamic_typesupport_member_id_t + get_member_id(const std::string & name) const; + + RCLCPP_PUBLIC + rosidl_dynamic_typesupport_member_id_t + get_array_index(size_t index) const; + + RCLCPP_PUBLIC + rosidl_dynamic_typesupport_member_id_t + get_array_index(const std::string & name) const; + + + // METHODS ======================================================================================= + RCLCPP_PUBLIC + DynamicData + clone() const; + + RCLCPP_PUBLIC + DynamicData::SharedPtr + clone_shared() const; + + RCLCPP_PUBLIC + bool + equals(const DynamicData & other) const; + + RCLCPP_PUBLIC + DynamicData::SharedPtr + loan_value(rosidl_dynamic_typesupport_member_id_t id); + + RCLCPP_PUBLIC + DynamicData::SharedPtr + loan_value(const std::string & name); + + RCLCPP_PUBLIC + void + clear_all_values(); + + RCLCPP_PUBLIC + void + clear_nonkey_values(); + + RCLCPP_PUBLIC + void + clear_value(rosidl_dynamic_typesupport_member_id_t id); + + RCLCPP_PUBLIC + void + clear_value(const std::string & name); + + RCLCPP_PUBLIC + void + clear_sequence(); + + RCLCPP_PUBLIC + rosidl_dynamic_typesupport_member_id_t + insert_sequence_data(); + + RCLCPP_PUBLIC + void + remove_sequence_data(rosidl_dynamic_typesupport_member_id_t index); + + RCLCPP_PUBLIC + void + print() const; + + RCLCPP_PUBLIC + bool + serialize(std::shared_ptr buffer); + + RCLCPP_PUBLIC + bool + deserialize(std::shared_ptr buffer); + + + // MEMBER ACCESS TEMPLATES ======================================================================= + /** + * Since we're in a ROS layer, these should support all ROS interface C++ types as found in: + * https://docs.ros.org/en/rolling/Concepts/About-ROS-Interfaces.html + * + * Explicitly: + * - Basic types: bool, byte, char + * - Float types: float, double + * - Int types: int8_t, int16_t, int32_t, int64_t + * - Unsigned int types: uint8_t, uint16_t, uint32_t, uint64_t + * - String types: std::string, std::u16string + */ + + template + ValueT + get_value(rosidl_dynamic_typesupport_member_id_t id); + + template + ValueT + get_value(const std::string & name); + + template + void + set_value(rosidl_dynamic_typesupport_member_id_t id, ValueT value); + + template + void + set_value(const std::string & name, ValueT value); + + template + rosidl_dynamic_typesupport_member_id_t + insert_value(ValueT value); + + + // BOUNDED STRING MEMBER ACCESS ================================================================== + RCLCPP_PUBLIC + const std::string + get_bounded_string_value(rosidl_dynamic_typesupport_member_id_t id, size_t string_bound); + + RCLCPP_PUBLIC + const std::string + get_bounded_string_value(const std::string & name, size_t string_bound); + + RCLCPP_PUBLIC + const std::u16string + get_bounded_wstring_value(rosidl_dynamic_typesupport_member_id_t id, size_t wstring_bound); + + RCLCPP_PUBLIC + const std::u16string + get_bounded_wstring_value(const std::string & name, size_t wstring_bound); + + RCLCPP_PUBLIC + void + set_bounded_string_value( + rosidl_dynamic_typesupport_member_id_t id, const std::string value, size_t string_bound); + + RCLCPP_PUBLIC + void + set_bounded_string_value(const std::string & name, const std::string value, size_t string_bound); + + RCLCPP_PUBLIC + void + set_bounded_wstring_value( + rosidl_dynamic_typesupport_member_id_t id, const std::u16string value, size_t wstring_bound); + + RCLCPP_PUBLIC + void + set_bounded_wstring_value( + const std::string & name, const std::u16string value, size_t wstring_bound); + + RCLCPP_PUBLIC + rosidl_dynamic_typesupport_member_id_t + insert_bounded_string_value(const std::string value, size_t string_bound); + + RCLCPP_PUBLIC + rosidl_dynamic_typesupport_member_id_t + insert_bounded_wstring_value(const std::u16string value, size_t wstring_bound); + + + // NESTED MEMBER ACCESS ========================================================================== + RCLCPP_PUBLIC + DynamicData + get_complex_value(rosidl_dynamic_typesupport_member_id_t id); + + RCLCPP_PUBLIC + DynamicData + get_complex_value(const std::string & name); + + RCLCPP_PUBLIC + DynamicData::SharedPtr + get_complex_value_shared(rosidl_dynamic_typesupport_member_id_t id); + + RCLCPP_PUBLIC + DynamicData::SharedPtr + get_complex_value_shared(const std::string & name); + + RCLCPP_PUBLIC + void + set_complex_value(rosidl_dynamic_typesupport_member_id_t id, DynamicData & value); + + RCLCPP_PUBLIC + void + set_complex_value(const std::string & name, DynamicData & value); + + RCLCPP_PUBLIC + rosidl_dynamic_typesupport_member_id_t + insert_complex_value_copy(const DynamicData & value); + + RCLCPP_PUBLIC + rosidl_dynamic_typesupport_member_id_t + insert_complex_value(DynamicData & value); + +protected: + // NOTE(methylDragon): + // This is just here to extend the lifetime of the serialization support + // It isn't actually used by the builder since the builder should compose its own support + // + // ... Though ideally it should be the exact same support as the one stored in the + // DynamicSerializationSupport + DynamicSerializationSupport::SharedPtr serialization_support_; + + std::shared_ptr rosidl_dynamic_data_; + + bool is_loaned_; + DynamicData::SharedPtr parent_data_; // Used for returning the loaned value, and lifetime management + +private: + RCLCPP_PUBLIC + DynamicData(); + + RCLCPP_PUBLIC + bool + match_serialization_support_( + const DynamicSerializationSupport & serialization_support, + const rosidl_dynamic_typesupport_dynamic_data_t & dynamic_data); +}; + + +} // namespace dynamic_typesupport +} // namespace rclcpp + +#endif // RCLCPP__DYNAMIC_TYPESUPPORT__DYNAMIC_DATA_HPP_ diff --git a/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message.hpp b/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message.hpp new file mode 100644 index 0000000000..d39fae07e1 --- /dev/null +++ b/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message.hpp @@ -0,0 +1,105 @@ +// Copyright 2023 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef RCLCPP__DYNAMIC_TYPESUPPORT__DYNAMIC_MESSAGE_HPP_ +#define RCLCPP__DYNAMIC_TYPESUPPORT__DYNAMIC_MESSAGE_HPP_ + + +#include +#include + +#include "rclcpp/dynamic_typesupport/dynamic_data.hpp" +#include "rclcpp/dynamic_typesupport/dynamic_serialization_support.hpp" +#include "rclcpp/dynamic_typesupport/dynamic_type.hpp" +#include "rclcpp/dynamic_typesupport/dynamic_type_builder.hpp" +#include "rclcpp/macros.hpp" +#include "rclcpp/visibility_control.hpp" + +#include + + +namespace rclcpp +{ +namespace dynamic_typesupport +{ + + +/// Thin wrapper around DynamicData object for message pubsub +/** + * This class: + * - Manages the lifetime of the raw pointer. + * - Exposes getter methods to get the raw pointer and shared pointers + * - Exposes the underlying serialization support API + * + * Ownership: + * - This class borrows the rosidl_dynamic_typesupport_serialization_support_t stored in the passed + * DynamicSerializationSupport. So it cannot outlive the DynamicSerializationSupport. + * - The DynamicSerializationSupport's rosidl_dynamic_typesupport_serialization_support_t pointer + * must point to the same location in memory as the stored raw pointer! + */ +class DynamicMessage final : public DynamicData +{ +public: + RCLCPP_SMART_PTR_ALIASES_ONLY(DynamicMessage) + + // CONSTRUCTION ================================================================================== + // Most constructors require a passed in DynamicSerializationSupport::SharedPtr, to extend the + // lifetime of the serialization support (if the constructor cannot otherwise get it from args). + // + // In cases where a dynamic data pointer is passed, the serialization support composed by + // the data should be the exact same object managed by the DynamicSerializationSupport, + // otherwise the lifetime management will not work properly. + + /// Construct a new DynamicMessage with the provided dynamic type builder + RCLCPP_PUBLIC + explicit DynamicMessage(std::shared_ptr dynamic_type_builder); + + /// Construct a new DynamicMessage with the provided dynamic type + RCLCPP_PUBLIC + explicit DynamicMessage(std::shared_ptr dynamic_type); + + /// Assume ownership of raw pointer + RCLCPP_PUBLIC + DynamicMessage( + DynamicSerializationSupport::SharedPtr serialization_support, + rosidl_dynamic_typesupport_dynamic_data_t * rosidl_dynamic_data); + + /// Copy shared pointer + RCLCPP_PUBLIC + DynamicMessage( + DynamicSerializationSupport::SharedPtr serialization_support, + std::shared_ptr rosidl_dynamic_data); + + /// Loaning constructor + /// Must only be called with raw ptr obtained from loaning! + // NOTE(methylDragon): I'd put this in protected, but I need this exposed to + // enable_shared_from_this... + RCLCPP_PUBLIC + DynamicMessage( + DynamicData::SharedPtr parent_data, + rosidl_dynamic_typesupport_dynamic_data_t * rosidl_loaned_data); + + // NOTE(methylDragon): Deliberately no constructor from description to nudge users towards using + // construction from dynamic type/builder, which is more efficient + +private: + RCLCPP_PUBLIC + DynamicMessage(); +}; + + +} // namespace dynamic_typesupport +} // namespace rclcpp + +#endif // RCLCPP__DYNAMIC_TYPESUPPORT__DYNAMIC_MESSAGE_HPP_ diff --git a/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message_type.hpp b/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message_type.hpp new file mode 100644 index 0000000000..fd33180675 --- /dev/null +++ b/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message_type.hpp @@ -0,0 +1,93 @@ +// Copyright 2023 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef RCLCPP__DYNAMIC_TYPESUPPORT__DYNAMIC_MESSAGE_TYPE_HPP_ +#define RCLCPP__DYNAMIC_TYPESUPPORT__DYNAMIC_MESSAGE_TYPE_HPP_ + +#include +#include + +#include "rclcpp/dynamic_typesupport/dynamic_serialization_support.hpp" +#include "rclcpp/dynamic_typesupport/dynamic_type.hpp" +#include "rclcpp/dynamic_typesupport/dynamic_type_builder.hpp" +#include "rclcpp/macros.hpp" +#include "rclcpp/visibility_control.hpp" + +#include + + +namespace rclcpp +{ +namespace dynamic_typesupport +{ + + +/// Thin wrapper around DynamicType object for message pubsub type representation +/** + * This class: + * - Manages the lifetime of the raw pointer. + * - Exposes getter methods to get the raw pointer and shared pointers + * - Exposes the underlying serialization support API + * + * Ownership: + * - This class borrows the rosidl_dynamic_typesupport_serialization_support_t stored in the passed + * DynamicSerializationSupport. So it cannot outlive the DynamicSerializationSupport. + * - The DynamicSerializationSupport's rosidl_dynamic_typesupport_serialization_support_t pointer + * must point to the same location in memory as the stored raw pointer! + */ +class DynamicMessageType final : public DynamicType +{ +public: + RCLCPP_SMART_PTR_ALIASES_ONLY(DynamicMessageType) + + // CONSTRUCTION ================================================================================== + // Most constructors require a passed in DynamicSerializationSupport::SharedPtr, to extend the + // lifetime of the serialization support (if the constructor cannot otherwise get it from args). + // + // In cases where a dynamic type pointer is passed, the serialization support composed by + // the type should be the exact same object managed by the DynamicSerializationSupport, + // otherwise the lifetime management will not work properly. + + /// Construct a new DynamicType with the provided dynamic type builder + RCLCPP_PUBLIC + explicit DynamicMessageType(std::shared_ptr dynamic_type_builder); + + /// Assume ownership of raw pointer + RCLCPP_PUBLIC + DynamicMessageType( + DynamicSerializationSupport::SharedPtr serialization_support, + rosidl_dynamic_typesupport_dynamic_type_t * rosidl_dynamic_type); + + /// Copy shared pointer + RCLCPP_PUBLIC + DynamicMessageType( + DynamicSerializationSupport::SharedPtr serialization_support, + std::shared_ptr rosidl_dynamic_type); + + /// From description + RCLCPP_PUBLIC + DynamicMessageType( + DynamicSerializationSupport::SharedPtr serialization_support, + const rosidl_runtime_c__type_description__TypeDescription * description); + +private: + RCLCPP_PUBLIC + DynamicMessageType(); +}; + + +} // namespace dynamic_typesupport +} // namespace rclcpp + +#endif // RCLCPP__DYNAMIC_TYPESUPPORT__DYNAMIC_MESSAGE_TYPE_HPP_ diff --git a/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_serialization_support.hpp b/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_serialization_support.hpp new file mode 100644 index 0000000000..932e6a2d94 --- /dev/null +++ b/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_serialization_support.hpp @@ -0,0 +1,110 @@ +// Copyright 2023 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef RCLCPP__DYNAMIC_TYPESUPPORT__DYNAMIC_SERIALIZATION_SUPPORT_HPP_ +#define RCLCPP__DYNAMIC_TYPESUPPORT__DYNAMIC_SERIALIZATION_SUPPORT_HPP_ + +#include +#include + +#include "rclcpp/macros.hpp" +#include "rclcpp/visibility_control.hpp" + +#include + + +namespace rclcpp +{ +namespace dynamic_typesupport +{ + +/// Utility wrapper class for rosidl_dynamic_typesupport_serialization_support_t * +/** + * This class: + * - Manages the lifetime of the raw pointer. + * - Exposes getter methods to get the raw pointer and shared pointers + * - Exposes the underlying serialization support API + * + * Ownership: + * - This class, similarly to the rosidl_dynamic_typesupport_serialization_support_t, must outlive + * all downstream usages of the serialization support. + */ +class DynamicSerializationSupport : public std::enable_shared_from_this +{ +public: + RCLCPP_SMART_PTR_ALIASES_ONLY(DynamicSerializationSupport) + + // CONSTRUCTION ================================================================================== + /// Get the rmw middleware implementation specific serialization support (configured by name) + RCLCPP_PUBLIC + explicit DynamicSerializationSupport(const std::string & serialization_library_name = nullptr); + + /// Assume ownership of raw pointer + RCLCPP_PUBLIC + explicit DynamicSerializationSupport( + rosidl_dynamic_typesupport_serialization_support_t * rosidl_serialization_support); + + /// Copy shared pointer + RCLCPP_PUBLIC + DynamicSerializationSupport( // NOLINT(explicit) + std::shared_ptr serialization_support); + + /// Move constructor + RCLCPP_PUBLIC + DynamicSerializationSupport(DynamicSerializationSupport && other) noexcept; + + /// Move assignment + RCLCPP_PUBLIC + DynamicSerializationSupport & operator=(DynamicSerializationSupport && other) noexcept; + + RCLCPP_PUBLIC + virtual ~DynamicSerializationSupport(); + + + // GETTERS ======================================================================================= + RCLCPP_PUBLIC + const std::string + get_library_identifier() const; + + RCLCPP_PUBLIC + rosidl_dynamic_typesupport_serialization_support_t * + get_rosidl_serialization_support(); + + RCLCPP_PUBLIC + const rosidl_dynamic_typesupport_serialization_support_t * + get_rosidl_serialization_support() const; + + RCLCPP_PUBLIC + std::shared_ptr + get_shared_rosidl_serialization_support(); + + RCLCPP_PUBLIC + std::shared_ptr + get_shared_rosidl_serialization_support() const; + +protected: + RCLCPP_DISABLE_COPY(DynamicSerializationSupport) + + std::shared_ptr rosidl_serialization_support_; + +private: + RCLCPP_PUBLIC + DynamicSerializationSupport(); +}; + + +} // namespace dynamic_typesupport +} // namespace rclcpp + +#endif // RCLCPP__DYNAMIC_TYPESUPPORT__DYNAMIC_SERIALIZATION_SUPPORT_HPP_ diff --git a/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_type.hpp b/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_type.hpp new file mode 100644 index 0000000000..e0d9660c22 --- /dev/null +++ b/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_type.hpp @@ -0,0 +1,196 @@ +// Copyright 2023 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef RCLCPP__DYNAMIC_TYPESUPPORT__DYNAMIC_TYPE_HPP_ +#define RCLCPP__DYNAMIC_TYPESUPPORT__DYNAMIC_TYPE_HPP_ + +#include +#include + +#include "rclcpp/dynamic_typesupport/dynamic_serialization_support.hpp" +#include "rclcpp/macros.hpp" +#include "rclcpp/visibility_control.hpp" + +#include + + +namespace rclcpp +{ +namespace dynamic_typesupport +{ + + +class DynamicData; +class DynamicTypeBuilder; + +/// Utility wrapper class for rosidl_dynamic_typesupport_dynamic_type_t * +/** + * This class: + * - Manages the lifetime of the raw pointer. + * - Exposes getter methods to get the raw pointer and shared pointers + * - Exposes the underlying serialization support API + * + * Ownership: + * - This class borrows the rosidl_dynamic_typesupport_serialization_support_t stored in the passed + * DynamicSerializationSupport. So it cannot outlive the DynamicSerializationSupport. + * - The DynamicSerializationSupport's rosidl_dynamic_typesupport_serialization_support_t pointer + * must point to the same location in memory as the stored raw pointer! + */ +class DynamicType : public std::enable_shared_from_this +{ +public: + RCLCPP_SMART_PTR_ALIASES_ONLY(DynamicType) + + // CONSTRUCTION ================================================================================== + // Most constructors require a passed in DynamicSerializationSupport::SharedPtr, to extend the + // lifetime of the serialization support (if the constructor cannot otherwise get it from args). + // + // In cases where a dynamic type pointer is passed, the serialization support composed by + // the type should be the exact same object managed by the DynamicSerializationSupport, + // otherwise the lifetime management will not work properly. + + /// Construct a new DynamicType with the provided dynamic type builder + RCLCPP_PUBLIC + explicit DynamicType(std::shared_ptr dynamic_type_builder); + + /// Assume ownership of raw pointer + RCLCPP_PUBLIC + DynamicType( + DynamicSerializationSupport::SharedPtr serialization_support, + rosidl_dynamic_typesupport_dynamic_type_t * rosidl_dynamic_type); + + /// Copy shared pointer + RCLCPP_PUBLIC + DynamicType( + DynamicSerializationSupport::SharedPtr serialization_support, + std::shared_ptr rosidl_dynamic_type); + + /// From description + RCLCPP_PUBLIC + DynamicType( + DynamicSerializationSupport::SharedPtr serialization_support, + const rosidl_runtime_c__type_description__TypeDescription * description); + + /// Copy constructor + RCLCPP_PUBLIC + DynamicType(const DynamicType & other); + + /// Move constructor + RCLCPP_PUBLIC + DynamicType(DynamicType && other) noexcept; + + /// Copy assignment + RCLCPP_PUBLIC + DynamicType & operator=(const DynamicType & other); + + /// Move assignment + RCLCPP_PUBLIC + DynamicType & operator=(DynamicType && other) noexcept; + + RCLCPP_PUBLIC + virtual ~DynamicType(); + + /// Swaps the serialization support if serialization_support is populated + RCLCPP_PUBLIC + void + init_from_description( + const rosidl_runtime_c__type_description__TypeDescription * description, + DynamicSerializationSupport::SharedPtr serialization_support = nullptr); + + // GETTERS ======================================================================================= + RCLCPP_PUBLIC + const std::string + get_library_identifier() const; + + RCLCPP_PUBLIC + const std::string + get_name() const; + + RCLCPP_PUBLIC + size_t + get_member_count() const; + + RCLCPP_PUBLIC + rosidl_dynamic_typesupport_dynamic_type_t * + get_rosidl_dynamic_type(); + + RCLCPP_PUBLIC + const rosidl_dynamic_typesupport_dynamic_type_t * + get_rosidl_dynamic_type() const; + + RCLCPP_PUBLIC + std::shared_ptr + get_shared_rosidl_dynamic_type(); + + RCLCPP_PUBLIC + std::shared_ptr + get_shared_rosidl_dynamic_type() const; + + RCLCPP_PUBLIC + DynamicSerializationSupport::SharedPtr + get_shared_dynamic_serialization_support(); + + RCLCPP_PUBLIC + std::shared_ptr + get_shared_dynamic_serialization_support() const; + + + // METHODS ======================================================================================= + RCLCPP_PUBLIC + DynamicType + clone() const; + + RCLCPP_PUBLIC + DynamicType::SharedPtr + clone_shared() const; + + RCLCPP_PUBLIC + bool + equals(const DynamicType & other) const; + + RCLCPP_PUBLIC + DynamicData + build_data(); + + RCLCPP_PUBLIC + std::shared_ptr + build_data_shared(); + +protected: + // NOTE(methylDragon): + // This is just here to extend the lifetime of the serialization support + // It isn't actually used by the builder since the builder should compose its own support + // + // ... Though ideally it should be the exact same support as the one stored in the + // DynamicSerializationSupport + DynamicSerializationSupport::SharedPtr serialization_support_; + + std::shared_ptr rosidl_dynamic_type_; + +private: + RCLCPP_PUBLIC + DynamicType(); + + RCLCPP_PUBLIC + bool + match_serialization_support_( + const DynamicSerializationSupport & serialization_support, + const rosidl_dynamic_typesupport_dynamic_type_t & rosidl_dynamic_type); +}; + + +} // namespace dynamic_typesupport +} // namespace rclcpp + +#endif // RCLCPP__DYNAMIC_TYPESUPPORT__DYNAMIC_TYPE_HPP_ diff --git a/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_type_builder.hpp b/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_type_builder.hpp new file mode 100644 index 0000000000..62199c838a --- /dev/null +++ b/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_type_builder.hpp @@ -0,0 +1,318 @@ +// Copyright 2023 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef RCLCPP__DYNAMIC_TYPESUPPORT__DYNAMIC_TYPE_BUILDER_HPP_ +#define RCLCPP__DYNAMIC_TYPESUPPORT__DYNAMIC_TYPE_BUILDER_HPP_ + +#include +#include + +#include "rclcpp/dynamic_typesupport/dynamic_serialization_support.hpp" +#include "rclcpp/macros.hpp" +#include "rclcpp/visibility_control.hpp" + +#include + + +namespace rclcpp +{ +namespace dynamic_typesupport +{ + +class DynamicData; +class DynamicType; + +/// Utility wrapper class for rosidl_dynamic_typesupport_dynamic_type_builder_t * +/** + * This class: + * - Manages the lifetime of the raw pointer. + * - Exposes getter methods to get the raw pointer and shared pointers + * - Exposes the underlying serialization support API + * + * Ownership: + * - This class borrows the rosidl_dynamic_typesupport_serialization_support_t stored in the passed + * DynamicSerializationSupport. So it cannot outlive the DynamicSerializationSupport. + * - The DynamicSerializationSupport's rosidl_dynamic_typesupport_serialization_support_t pointer + * must point to the same location in memory as the stored raw pointer! + */ +class DynamicTypeBuilder : public std::enable_shared_from_this +{ +public: + RCLCPP_SMART_PTR_ALIASES_ONLY(DynamicTypeBuilder) + + // CONSTRUCTION ================================================================================== + // All constructors require a passed in DynamicSerializationSupport::SharedPtr, to extend the + // lifetime of the serialization support. + // + // In cases where a dynamic type builder pointer is passed, the serialization support composed by + // the builder should be the exact same object managed by the DynamicSerializationSupport, + // otherwise the lifetime management will not work properly. + + /// Construct a new DynamicTypeBuilder with the provided serialization support + RCLCPP_PUBLIC + DynamicTypeBuilder( + DynamicSerializationSupport::SharedPtr serialization_support, + const std::string & name); + + /// Assume ownership of raw pointer + RCLCPP_PUBLIC + DynamicTypeBuilder( + DynamicSerializationSupport::SharedPtr serialization_support, + rosidl_dynamic_typesupport_dynamic_type_builder_t * dynamic_type_builder); + + /// Copy shared pointer + RCLCPP_PUBLIC + DynamicTypeBuilder( + DynamicSerializationSupport::SharedPtr serialization_support, + std::shared_ptr dynamic_type_builder); + + /// Copy constructor + RCLCPP_PUBLIC + DynamicTypeBuilder(const DynamicTypeBuilder & other); + + /// Move constructor + RCLCPP_PUBLIC + DynamicTypeBuilder(DynamicTypeBuilder && other) noexcept; + + /// Copy assignment + RCLCPP_PUBLIC + DynamicTypeBuilder & operator=(const DynamicTypeBuilder & other); + + /// Move assignment + RCLCPP_PUBLIC + DynamicTypeBuilder & operator=(DynamicTypeBuilder && other) noexcept; + + /// From description + RCLCPP_PUBLIC + DynamicTypeBuilder( + DynamicSerializationSupport::SharedPtr serialization_support, + const rosidl_runtime_c__type_description__TypeDescription * description); + + RCLCPP_PUBLIC + virtual ~DynamicTypeBuilder(); + + /// Swaps the serialization support if serialization_support is populated + RCLCPP_PUBLIC + void + init_from_description( + const rosidl_runtime_c__type_description__TypeDescription * description, + DynamicSerializationSupport::SharedPtr serialization_support = nullptr); + + + // GETTERS ======================================================================================= + RCLCPP_PUBLIC + const std::string + get_library_identifier() const; + + RCLCPP_PUBLIC + const std::string + get_name() const; + + RCLCPP_PUBLIC + rosidl_dynamic_typesupport_dynamic_type_builder_t * + get_rosidl_dynamic_type_builder(); + + RCLCPP_PUBLIC + const rosidl_dynamic_typesupport_dynamic_type_builder_t * + get_rosidl_dynamic_type_builder() const; + + RCLCPP_PUBLIC + std::shared_ptr + get_shared_rosidl_dynamic_type_builder(); + + RCLCPP_PUBLIC + std::shared_ptr + get_shared_rosidl_dynamic_type_builder() const; + + RCLCPP_PUBLIC + DynamicSerializationSupport::SharedPtr + get_shared_dynamic_serialization_support(); + + RCLCPP_PUBLIC + std::shared_ptr + get_shared_dynamic_serialization_support() const; + + + // METHODS ======================================================================================= + RCLCPP_PUBLIC + void + set_name(const std::string & name); + + RCLCPP_PUBLIC + DynamicTypeBuilder + clone() const; + + RCLCPP_PUBLIC + DynamicTypeBuilder::SharedPtr + clone_shared() const; + + RCLCPP_PUBLIC + void + clear(); + + RCLCPP_PUBLIC + DynamicData + build_data(); + + RCLCPP_PUBLIC + std::shared_ptr + build_data_shared(); + + RCLCPP_PUBLIC + DynamicType + build_type(); + + RCLCPP_PUBLIC + std::shared_ptr + build_type_shared(); + + + // ADD MEMBERS TEMPLATES ========================================================================= + /** + * Since we're in a ROS layer, these should support all ROS interface C++ types as found in: + * https://docs.ros.org/en/rolling/Concepts/About-ROS-Interfaces.html + * + * Explicitly: + * - Basic types: bool, byte, char + * - Float types: float, double + * - Int types: int8_t, int16_t, int32_t, int64_t + * - Unsigned int types: uint8_t, uint16_t, uint32_t, uint64_t + * - String types: std::string, std::u16string + */ + + template + void + add_member(rosidl_dynamic_typesupport_member_id_t id, const std::string & name); + + template + void + add_array_member( + rosidl_dynamic_typesupport_member_id_t id, const std::string & name, size_t array_length); + + template + void + add_unbounded_sequence_member( + rosidl_dynamic_typesupport_member_id_t id, const std::string & name); + + template + void + add_bounded_sequence_member( + rosidl_dynamic_typesupport_member_id_t id, const std::string & name, size_t sequence_bound); + + + // ADD BOUNDED STRING MEMBERS ==================================================================== + RCLCPP_PUBLIC + void + add_bounded_string_member( + rosidl_dynamic_typesupport_member_id_t id, const std::string & name, size_t string_bound); + + RCLCPP_PUBLIC + void + add_bounded_wstring_member( + rosidl_dynamic_typesupport_member_id_t id, const std::string & name, size_t wstring_bound); + + RCLCPP_PUBLIC + void + add_bounded_string_array_member( + rosidl_dynamic_typesupport_member_id_t id, const std::string & name, + size_t string_bound, size_t array_length); + + RCLCPP_PUBLIC + void + add_bounded_wstring_array_member( + rosidl_dynamic_typesupport_member_id_t id, const std::string & name, + size_t wstring_bound, size_t array_length); + + RCLCPP_PUBLIC + void + add_bounded_string_unbounded_sequence_member( + rosidl_dynamic_typesupport_member_id_t id, const std::string & name, size_t string_bound); + + RCLCPP_PUBLIC + void + add_bounded_wstring_unbounded_sequence_member( + rosidl_dynamic_typesupport_member_id_t id, const std::string & name, size_t wstring_bound); + + RCLCPP_PUBLIC + void + add_bounded_string_bounded_sequence_member( + rosidl_dynamic_typesupport_member_id_t id, const std::string & name, + size_t string_bound, size_t sequence_bound); + + RCLCPP_PUBLIC + void + add_bounded_wstring_bounded_sequence_member( + rosidl_dynamic_typesupport_member_id_t id, const std::string & name, + size_t wstring_bound, size_t sequence_bound); + + + // ADD NESTED MEMBERS ============================================================================ + RCLCPP_PUBLIC + void + add_complex_member( + rosidl_dynamic_typesupport_member_id_t id, const std::string & name, + DynamicType & nested_type); + + RCLCPP_PUBLIC + void + add_complex_array_member( + rosidl_dynamic_typesupport_member_id_t id, const std::string & name, + DynamicType & nested_type, size_t array_length); + + RCLCPP_PUBLIC + void + add_complex_unbounded_sequence_member( + rosidl_dynamic_typesupport_member_id_t id, const std::string & name, + DynamicType & nested_type); + + RCLCPP_PUBLIC + void + add_complex_bounded_sequence_member( + rosidl_dynamic_typesupport_member_id_t id, const std::string & name, + DynamicType & nested_type, size_t sequence_bound); + +protected: + // NOTE(methylDragon): + // This is just here to extend the lifetime of the serialization support + // It isn't actually used by the builder since the builder should compose its own support + // + // ... Though ideally it should be the exact same support as the one stored in the + // DynamicSerializationSupport + DynamicSerializationSupport::SharedPtr serialization_support_; + + std::shared_ptr rosidl_dynamic_type_builder_; + +private: + RCLCPP_PUBLIC + DynamicTypeBuilder(); + + RCLCPP_PUBLIC + void + init_from_serialization_support_( + DynamicSerializationSupport::SharedPtr serialization_support, + const std::string & name); + + RCLCPP_PUBLIC + bool + match_serialization_support_( + const DynamicSerializationSupport & serialization_support, + const rosidl_dynamic_typesupport_dynamic_type_builder_t & dynamic_type_builder); +}; + + +} // namespace dynamic_typesupport +} // namespace rclcpp + + +#endif // RCLCPP__DYNAMIC_TYPESUPPORT__DYNAMIC_TYPE_BUILDER_HPP_ diff --git a/rclcpp/include/rclcpp/rclcpp.hpp b/rclcpp/include/rclcpp/rclcpp.hpp index f1d751ff3f..ab4b54a0dd 100644 --- a/rclcpp/include/rclcpp/rclcpp.hpp +++ b/rclcpp/include/rclcpp/rclcpp.hpp @@ -117,6 +117,19 @@ * - Allocator related items: * - rclcpp/allocator/allocator_common.hpp * - rclcpp/allocator/allocator_deleter.hpp + * - Dynamic typesupport wrappers + * - rclcpp::dynamic_typesupport::DynamicData + * - rclcpp::dynamic_typesupport::DynamicMessage + * - rclcpp::dynamic_typesupport::DynamicMessageType + * - rclcpp::dynamic_typesupport::DynamicSerializationSupport + * - rclcpp::dynamic_typesupport::DynamicTypeBuilder + * - rclcpp::dynamic_typesupport::DynamicType + * - rclcpp/dynamic_typesupport/dynamic_data.hpp + * - rclcpp/dynamic_typesupport/dynamic_message.hpp + * - rclcpp/dynamic_typesupport/dynamic_message_type.hpp + * - rclcpp/dynamic_typesupport/dynamic_serialization_support.hpp + * - rclcpp/dynamic_typesupport/dynamic_type_builder.hpp + * - rclcpp/dynamic_typesupport/dynamic_type.hpp * - Generic publisher * - rclcpp::Node::create_generic_publisher() * - rclcpp::GenericPublisher diff --git a/rclcpp/package.xml b/rclcpp/package.xml index 38773e2ec2..f7c89260bc 100644 --- a/rclcpp/package.xml +++ b/rclcpp/package.xml @@ -39,6 +39,7 @@ rcpputils rcutils rmw + rosidl_dynamic_typesupport statistics_msgs tracetools diff --git a/rclcpp/src/rclcpp/dynamic_typesupport/dynamic_data.cpp b/rclcpp/src/rclcpp/dynamic_typesupport/dynamic_data.cpp new file mode 100644 index 0000000000..f953e44a80 --- /dev/null +++ b/rclcpp/src/rclcpp/dynamic_typesupport/dynamic_data.cpp @@ -0,0 +1,642 @@ +// Copyright 2023 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include + +#include "rclcpp/dynamic_typesupport/dynamic_data.hpp" +#include "rclcpp/dynamic_typesupport/dynamic_serialization_support.hpp" +#include "rclcpp/dynamic_typesupport/dynamic_type.hpp" +#include "rclcpp/dynamic_typesupport/dynamic_type_builder.hpp" +#include "rclcpp/exceptions.hpp" +#include "rcutils/logging_macros.h" + +#include +#include +#include + +using rclcpp::dynamic_typesupport::DynamicData; +using rclcpp::dynamic_typesupport::DynamicSerializationSupport; +using rclcpp::dynamic_typesupport::DynamicType; +using rclcpp::dynamic_typesupport::DynamicTypeBuilder; + +#ifndef RCLCPP__DYNAMIC_TYPESUPPORT__DETAIL__DYNAMIC_DATA_IMPL_HPP_ +// Template specialization implementations +#include "rclcpp/dynamic_typesupport/detail/dynamic_data_impl.hpp" +#endif + + +// CONSTRUCTION ================================================================================== +DynamicData::DynamicData(const DynamicTypeBuilder::SharedPtr dynamic_type_builder) +: serialization_support_(dynamic_type_builder->get_shared_dynamic_serialization_support()), + rosidl_dynamic_data_(nullptr), + is_loaned_(false), + parent_data_(nullptr) +{ + if (!serialization_support_) { + throw std::runtime_error("dynamic type could not bind serialization support!"); + } + + rosidl_dynamic_typesupport_dynamic_type_builder_t * rosidl_dynamic_type_builder = + dynamic_type_builder->get_rosidl_dynamic_type_builder(); + if (!rosidl_dynamic_type_builder) { + throw std::runtime_error("dynamic type builder cannot be nullptr!"); + } + + rosidl_dynamic_typesupport_dynamic_data_t * rosidl_dynamic_data = nullptr; + rosidl_dynamic_data = rosidl_dynamic_typesupport_dynamic_data_init_from_dynamic_type_builder( + rosidl_dynamic_type_builder); + if (!rosidl_dynamic_data) { + throw std::runtime_error("could not create new dynamic data object"); + } + + rosidl_dynamic_data_.reset( + rosidl_dynamic_data, + // Custom deleter + [](rosidl_dynamic_typesupport_dynamic_data_t * rosidl_dynamic_data)->void { + rosidl_dynamic_typesupport_dynamic_data_fini(rosidl_dynamic_data); + free(rosidl_dynamic_data); + }); +} + + +DynamicData::DynamicData(const DynamicType::SharedPtr dynamic_type) +: serialization_support_(dynamic_type->get_shared_dynamic_serialization_support()), + rosidl_dynamic_data_(nullptr), + is_loaned_(false), + parent_data_(nullptr) +{ + if (!serialization_support_) { + throw std::runtime_error("dynamic type could not bind serialization support!"); + } + + rosidl_dynamic_typesupport_dynamic_type_t * rosidl_dynamic_type = + dynamic_type->get_rosidl_dynamic_type(); + if (!rosidl_dynamic_type) { + throw std::runtime_error("dynamic type cannot be nullptr!"); + } + + rosidl_dynamic_typesupport_dynamic_data_t * rosidl_dynamic_data = nullptr; + rosidl_dynamic_data = rosidl_dynamic_typesupport_dynamic_data_init_from_dynamic_type( + rosidl_dynamic_type); + if (!rosidl_dynamic_data) { + throw std::runtime_error("could not create new dynamic data object"); + } + + rosidl_dynamic_data_.reset( + rosidl_dynamic_data, + // Custom deleter + [](rosidl_dynamic_typesupport_dynamic_data_t * rosidl_dynamic_data)->void { + rosidl_dynamic_typesupport_dynamic_data_fini(rosidl_dynamic_data); + free(rosidl_dynamic_data); + }); +} + + +DynamicData::DynamicData( + DynamicSerializationSupport::SharedPtr serialization_support, + rosidl_dynamic_typesupport_dynamic_data_t * rosidl_dynamic_data) +: serialization_support_(serialization_support), + rosidl_dynamic_data_(nullptr), + is_loaned_(false), + parent_data_(nullptr) +{ + if (!rosidl_dynamic_data) { + throw std::runtime_error("rosidl dynamic data cannot be nullptr!"); + } + if (serialization_support) { + if (!match_serialization_support_(*serialization_support, *rosidl_dynamic_data)) { + throw std::runtime_error( + "serialization support library identifier does not match dynamic data's!"); + } + } + + rosidl_dynamic_data_.reset( + rosidl_dynamic_data, + // Custom deleter + [](rosidl_dynamic_typesupport_dynamic_data_t * rosidl_dynamic_data)->void { + rosidl_dynamic_typesupport_dynamic_data_fini(rosidl_dynamic_data); + free(rosidl_dynamic_data); + }); +} + + +DynamicData::DynamicData( + DynamicSerializationSupport::SharedPtr serialization_support, + std::shared_ptr rosidl_dynamic_data) +: serialization_support_(serialization_support), + rosidl_dynamic_data_(rosidl_dynamic_data), + is_loaned_(false), + parent_data_(nullptr) +{ + if (!rosidl_dynamic_data) { + throw std::runtime_error("rosidl dynamic data cannot be nullptr!"); + } + if (serialization_support) { + if (!match_serialization_support_(*serialization_support, *rosidl_dynamic_data)) { + throw std::runtime_error( + "serialization support library identifier does not match dynamic data's!"); + } + } +} + + +DynamicData::DynamicData( + DynamicData::SharedPtr parent_data, + rosidl_dynamic_typesupport_dynamic_data_t * rosidl_loaned_data) +: DynamicData(parent_data->get_shared_dynamic_serialization_support(), rosidl_loaned_data) +{ + if (!parent_data) { + throw std::runtime_error("parent dynamic data cannot be nullptr!"); + } + if (!rosidl_loaned_data) { + throw std::runtime_error("loaned rosidl dynamic data cannot be nullptr!"); + } + + parent_data_ = parent_data; + is_loaned_ = true; +} + + +DynamicData::DynamicData(const DynamicData & other) +: enable_shared_from_this(), + serialization_support_(nullptr), + rosidl_dynamic_data_(nullptr), + is_loaned_(false), + parent_data_(nullptr) +{ + DynamicData out = other.clone(); + // We don't copy is_loaned_ or parent_data_ because it's a fresh copy now + std::swap(serialization_support_, out.serialization_support_); + std::swap(rosidl_dynamic_data_, out.rosidl_dynamic_data_); +} + + +DynamicData::DynamicData(DynamicData && other) noexcept +: serialization_support_(std::exchange(other.serialization_support_, nullptr)), + rosidl_dynamic_data_(std::exchange(other.rosidl_dynamic_data_, nullptr)), + is_loaned_(other.is_loaned_), + parent_data_(std::exchange(other.parent_data_, nullptr)) +{} + + +DynamicData & +DynamicData::operator=(const DynamicData & other) +{ + return *this = DynamicData(other); +} + + +DynamicData & +DynamicData::operator=(DynamicData && other) noexcept +{ + std::swap(serialization_support_, other.serialization_support_); + std::swap(rosidl_dynamic_data_, other.rosidl_dynamic_data_); + is_loaned_ = other.is_loaned_; + std::swap(parent_data_, other.parent_data_); + return *this; +} + + +DynamicData::~DynamicData() +{ + if (is_loaned_) { + if (!parent_data_) { + RCUTILS_LOG_ERROR("dynamic data is loaned, but parent is missing!!"); + } else { + rosidl_dynamic_typesupport_dynamic_data_return_loaned_value( + parent_data_->get_rosidl_dynamic_data(), get_rosidl_dynamic_data()); + } + } +} + + +bool +DynamicData::match_serialization_support_( + const DynamicSerializationSupport & serialization_support, + const rosidl_dynamic_typesupport_dynamic_data_t & rosidl_dynamic_type_data) +{ + bool out = true; + + if (serialization_support.get_library_identifier() != std::string( + rosidl_dynamic_type_data.serialization_support->library_identifier)) + { + RCUTILS_LOG_ERROR("serialization support library identifier does not match dynamic data's"); + out = false; + } + + // TODO(methylDragon): Can I do this?? Is it portable? + if (serialization_support.get_rosidl_serialization_support() != + rosidl_dynamic_type_data.serialization_support) + { + RCUTILS_LOG_ERROR("serialization support pointer does not match dynamic data's"); + out = false; + } + + return out; +} + + +// GETTERS ======================================================================================= +const std::string +DynamicData::get_library_identifier() const +{ + return std::string(rosidl_dynamic_data_->serialization_support->library_identifier); +} + + +const std::string +DynamicData::get_name() const +{ + size_t buf_length; + const char * buf = rosidl_dynamic_typesupport_dynamic_data_get_name( + get_rosidl_dynamic_data(), &buf_length); + return std::string(buf, buf_length); +} + + +rosidl_dynamic_typesupport_dynamic_data_t * +DynamicData::get_rosidl_dynamic_data() +{ + return rosidl_dynamic_data_.get(); +} + + +const rosidl_dynamic_typesupport_dynamic_data_t * +DynamicData::get_rosidl_dynamic_data() const +{ + return rosidl_dynamic_data_.get(); +} + + +std::shared_ptr +DynamicData::get_shared_rosidl_dynamic_data() +{ + return std::shared_ptr( + shared_from_this(), rosidl_dynamic_data_.get()); +} + + +std::shared_ptr +DynamicData::get_shared_rosidl_dynamic_data() const +{ + return std::shared_ptr( + shared_from_this(), rosidl_dynamic_data_.get()); +} + + +DynamicSerializationSupport::SharedPtr +DynamicData::get_shared_dynamic_serialization_support() +{ + return serialization_support_; +} + + +std::shared_ptr +DynamicData::get_shared_dynamic_serialization_support() const +{ + return serialization_support_; +} + + +size_t +DynamicData::get_item_count() const +{ + return rosidl_dynamic_typesupport_dynamic_data_get_item_count(get_rosidl_dynamic_data()); +} + + +rosidl_dynamic_typesupport_member_id_t +DynamicData::get_member_id(size_t index) const +{ + return rosidl_dynamic_typesupport_dynamic_data_get_member_id_at_index( + get_rosidl_dynamic_data(), index); +} + + +rosidl_dynamic_typesupport_member_id_t +DynamicData::get_member_id(const std::string & name) const +{ + return rosidl_dynamic_typesupport_dynamic_data_get_member_id_by_name( + get_rosidl_dynamic_data(), name.c_str(), name.size()); +} + + +rosidl_dynamic_typesupport_member_id_t +DynamicData::get_array_index(size_t index) const +{ + return rosidl_dynamic_typesupport_dynamic_data_get_array_index( + get_rosidl_dynamic_data(), index); +} + + +rosidl_dynamic_typesupport_member_id_t +DynamicData::get_array_index(const std::string & name) const +{ + return get_array_index(get_member_id(name)); +} + + +// METHODS ======================================================================================= +DynamicData +DynamicData::clone() const +{ + return DynamicData( + serialization_support_, + rosidl_dynamic_typesupport_dynamic_data_clone(get_rosidl_dynamic_data())); +} + + +DynamicData::SharedPtr +DynamicData::clone_shared() const +{ + return DynamicData::make_shared( + serialization_support_, + rosidl_dynamic_typesupport_dynamic_data_clone(get_rosidl_dynamic_data())); +} + + +bool +DynamicData::equals(const DynamicData & other) const +{ + if (get_library_identifier() != other.get_library_identifier()) { + throw std::runtime_error("library identifiers don't match"); + } + return rosidl_dynamic_typesupport_dynamic_data_equals( + get_rosidl_dynamic_data(), other.get_rosidl_dynamic_data()); +} + + +DynamicData::SharedPtr +DynamicData::loan_value(rosidl_dynamic_typesupport_member_id_t id) +{ + return DynamicData::make_shared( + shared_from_this(), + rosidl_dynamic_typesupport_dynamic_data_loan_value( + get_rosidl_dynamic_data(), id)); +} + + +DynamicData::SharedPtr +DynamicData::loan_value(const std::string & name) +{ + return loan_value(get_member_id(name)); +} + + +void +DynamicData::clear_all_values() +{ + rosidl_dynamic_typesupport_dynamic_data_clear_all_values(get_rosidl_dynamic_data()); +} + + +void +DynamicData::clear_nonkey_values() +{ + rosidl_dynamic_typesupport_dynamic_data_clear_nonkey_values(get_rosidl_dynamic_data()); +} + + +void +DynamicData::clear_value(rosidl_dynamic_typesupport_member_id_t id) +{ + rosidl_dynamic_typesupport_dynamic_data_clear_value(get_rosidl_dynamic_data(), id); +} + + +void +DynamicData::clear_value(const std::string & name) +{ + clear_value(get_member_id(name)); +} + + +void +DynamicData::clear_sequence() +{ + rosidl_dynamic_typesupport_dynamic_data_clear_sequence_data(get_rosidl_dynamic_data()); +} + + +rosidl_dynamic_typesupport_member_id_t +DynamicData::insert_sequence_data() +{ + rosidl_dynamic_typesupport_member_id_t out; + rosidl_dynamic_typesupport_dynamic_data_insert_sequence_data(get_rosidl_dynamic_data(), &out); + return out; +} + + +void +DynamicData::remove_sequence_data(rosidl_dynamic_typesupport_member_id_t index) +{ + rosidl_dynamic_typesupport_dynamic_data_remove_sequence_data( + get_rosidl_dynamic_data(), index); +} + + +void +DynamicData::print() const +{ + rosidl_dynamic_typesupport_dynamic_data_print(get_rosidl_dynamic_data()); +} + + +bool +DynamicData::serialize(std::shared_ptr buffer) +{ + return rosidl_dynamic_typesupport_dynamic_data_serialize( + get_rosidl_dynamic_data(), buffer.get()); +} + + +bool +DynamicData::deserialize(std::shared_ptr buffer) +{ + return rosidl_dynamic_typesupport_dynamic_data_deserialize( + get_rosidl_dynamic_data(), buffer.get()); +} + + +// MEMBER ACCESS =================================================================================== +// Defined in "detail/dynamic_data_impl.hpp" + + +// BOUNDED STRING MEMBER ACCESS ==================================================================== +const std::string +DynamicData::get_bounded_string_value( + rosidl_dynamic_typesupport_member_id_t id, size_t string_bound) +{ + size_t buf_length; + char * buf = nullptr; + rosidl_dynamic_typesupport_dynamic_data_get_bounded_string_value( + get_rosidl_dynamic_data(), id, &buf, &buf_length, string_bound); + auto out = std::string(buf, buf_length); + free(buf); + return out; +} + + +const std::string +DynamicData::get_bounded_string_value(const std::string & name, size_t string_bound) +{ + return get_bounded_string_value(get_member_id(name), string_bound); +} + + +const std::u16string +DynamicData::get_bounded_wstring_value( + rosidl_dynamic_typesupport_member_id_t id, size_t wstring_bound) +{ + size_t buf_length; + char16_t * buf = nullptr; + rosidl_dynamic_typesupport_dynamic_data_get_bounded_wstring_value( + get_rosidl_dynamic_data(), id, &buf, &buf_length, wstring_bound); + auto out = std::u16string(buf, buf_length); + free(buf); + return out; +} + + +const std::u16string +DynamicData::get_bounded_wstring_value(const std::string & name, size_t wstring_bound) +{ + return get_bounded_wstring_value(get_member_id(name), wstring_bound); +} + + +void +DynamicData::set_bounded_string_value( + rosidl_dynamic_typesupport_member_id_t id, const std::string value, size_t string_bound) +{ + rosidl_dynamic_typesupport_dynamic_data_set_bounded_string_value( + get_rosidl_dynamic_data(), id, value.c_str(), value.size(), string_bound); +} + + +void +DynamicData::set_bounded_string_value( + const std::string & name, const std::string value, size_t string_bound) +{ + set_bounded_string_value(get_member_id(name), value, string_bound); +} + + +void +DynamicData::set_bounded_wstring_value( + rosidl_dynamic_typesupport_member_id_t id, const std::u16string value, size_t wstring_bound) +{ + rosidl_dynamic_typesupport_dynamic_data_set_bounded_wstring_value( + get_rosidl_dynamic_data(), id, value.c_str(), value.size(), wstring_bound); +} + + +void +DynamicData::set_bounded_wstring_value( + const std::string & name, const std::u16string value, size_t wstring_bound) +{ + set_bounded_wstring_value(get_member_id(name), value, wstring_bound); +} + + +rosidl_dynamic_typesupport_member_id_t +DynamicData::insert_bounded_string_value(const std::string value, size_t string_bound) +{ + rosidl_dynamic_typesupport_member_id_t out; + rosidl_dynamic_typesupport_dynamic_data_insert_bounded_string_value( + get_rosidl_dynamic_data(), value.c_str(), value.size(), string_bound, &out); + return out; +} + + +rosidl_dynamic_typesupport_member_id_t +DynamicData::insert_bounded_wstring_value(const std::u16string value, size_t wstring_bound) +{ + rosidl_dynamic_typesupport_member_id_t out; + rosidl_dynamic_typesupport_dynamic_data_insert_bounded_wstring_value( + get_rosidl_dynamic_data(), value.c_str(), value.size(), wstring_bound, &out); + return out; +} + + +// NESTED MEMBER ACCESS ============================================================================ +DynamicData +DynamicData::get_complex_value(rosidl_dynamic_typesupport_member_id_t id) +{ + rosidl_dynamic_typesupport_dynamic_data_t * out_ptr = nullptr; + rosidl_dynamic_typesupport_dynamic_data_get_complex_value( + get_rosidl_dynamic_data(), id, &out_ptr); + return DynamicData(get_shared_dynamic_serialization_support(), out_ptr); +} + + +DynamicData +DynamicData::get_complex_value(const std::string & name) +{ + return get_complex_value(get_member_id(name)); +} + + +DynamicData::SharedPtr +DynamicData::get_complex_value_shared(rosidl_dynamic_typesupport_member_id_t id) +{ + rosidl_dynamic_typesupport_dynamic_data_t * out_ptr = nullptr; + rosidl_dynamic_typesupport_dynamic_data_get_complex_value( + get_rosidl_dynamic_data(), id, &out_ptr); + return DynamicData::make_shared(get_shared_dynamic_serialization_support(), out_ptr); +} + + +DynamicData::SharedPtr +DynamicData::get_complex_value_shared(const std::string & name) +{ + return get_complex_value_shared(get_member_id(name)); +} + + +void +DynamicData::set_complex_value( + rosidl_dynamic_typesupport_member_id_t id, DynamicData & value) +{ + rosidl_dynamic_typesupport_dynamic_data_set_complex_value( + get_rosidl_dynamic_data(), id, value.get_rosidl_dynamic_data()); +} + + +void +DynamicData::set_complex_value(const std::string & name, DynamicData & value) +{ + set_complex_value(get_member_id(name), value); +} + + +rosidl_dynamic_typesupport_member_id_t +DynamicData::insert_complex_value_copy(const DynamicData & value) +{ + rosidl_dynamic_typesupport_member_id_t out; + rosidl_dynamic_typesupport_dynamic_data_insert_complex_value_copy( + get_rosidl_dynamic_data(), value.get_rosidl_dynamic_data(), &out); + return out; +} + + +rosidl_dynamic_typesupport_member_id_t +DynamicData::insert_complex_value(DynamicData & value) +{ + rosidl_dynamic_typesupport_member_id_t out; + rosidl_dynamic_typesupport_dynamic_data_insert_complex_value( + get_rosidl_dynamic_data(), value.get_rosidl_dynamic_data(), &out); + return out; +} diff --git a/rclcpp/src/rclcpp/dynamic_typesupport/dynamic_message.cpp b/rclcpp/src/rclcpp/dynamic_typesupport/dynamic_message.cpp new file mode 100644 index 0000000000..550517a852 --- /dev/null +++ b/rclcpp/src/rclcpp/dynamic_typesupport/dynamic_message.cpp @@ -0,0 +1,61 @@ +// Copyright 2023 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include + +#include "rclcpp/dynamic_typesupport/dynamic_message.hpp" + +#include "rclcpp/dynamic_typesupport/dynamic_data.hpp" +#include "rclcpp/dynamic_typesupport/dynamic_serialization_support.hpp" +#include "rclcpp/dynamic_typesupport/dynamic_type.hpp" +#include "rclcpp/dynamic_typesupport/dynamic_type_builder.hpp" +#include "rclcpp/exceptions.hpp" +#include "rcutils/logging_macros.h" + +#include +#include +#include + +using rclcpp::dynamic_typesupport::DynamicMessage; +using rclcpp::dynamic_typesupport::DynamicSerializationSupport; +using rclcpp::dynamic_typesupport::DynamicType; +using rclcpp::dynamic_typesupport::DynamicTypeBuilder; + + +// CONSTRUCTION ================================================================================== +DynamicMessage::DynamicMessage(const DynamicTypeBuilder::SharedPtr dynamic_type_builder) +: DynamicData(dynamic_type_builder) {} + + +DynamicMessage::DynamicMessage(const DynamicType::SharedPtr dynamic_type) +: DynamicData(dynamic_type) {} + + +DynamicMessage::DynamicMessage( + DynamicSerializationSupport::SharedPtr serialization_support, + rosidl_dynamic_typesupport_dynamic_data_t * rosidl_dynamic_data) +: DynamicData(serialization_support, rosidl_dynamic_data) {} + + +DynamicMessage::DynamicMessage( + DynamicSerializationSupport::SharedPtr serialization_support, + std::shared_ptr rosidl_dynamic_data) +: DynamicData(serialization_support, rosidl_dynamic_data) {} + + +DynamicMessage::DynamicMessage( + DynamicData::SharedPtr parent_data, + rosidl_dynamic_typesupport_dynamic_data_t * rosidl_loaned_data) +: DynamicData(parent_data, rosidl_loaned_data) {} diff --git a/rclcpp/src/rclcpp/dynamic_typesupport/dynamic_message_type.cpp b/rclcpp/src/rclcpp/dynamic_typesupport/dynamic_message_type.cpp new file mode 100644 index 0000000000..3f6858fea5 --- /dev/null +++ b/rclcpp/src/rclcpp/dynamic_typesupport/dynamic_message_type.cpp @@ -0,0 +1,57 @@ +// Copyright 2023 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include + +#include "rclcpp/dynamic_typesupport/dynamic_message_type.hpp" + +#include "rclcpp/dynamic_typesupport/dynamic_data.hpp" +#include "rclcpp/dynamic_typesupport/dynamic_serialization_support.hpp" +#include "rclcpp/dynamic_typesupport/dynamic_type.hpp" +#include "rclcpp/dynamic_typesupport/dynamic_type_builder.hpp" +#include "rclcpp/exceptions.hpp" +#include "rcutils/logging_macros.h" + +#include +#include +#include + +using rclcpp::dynamic_typesupport::DynamicMessageType; +using rclcpp::dynamic_typesupport::DynamicSerializationSupport; +using rclcpp::dynamic_typesupport::DynamicType; +using rclcpp::dynamic_typesupport::DynamicTypeBuilder; + + +// CONSTRUCTION ==================================================================================== +DynamicMessageType::DynamicMessageType(DynamicTypeBuilder::SharedPtr dynamic_type_builder) +: DynamicType(dynamic_type_builder) {} + + +DynamicMessageType::DynamicMessageType( + DynamicSerializationSupport::SharedPtr serialization_support, + rosidl_dynamic_typesupport_dynamic_type_t * rosidl_dynamic_type) +: DynamicType(serialization_support, rosidl_dynamic_type) {} + + +DynamicMessageType::DynamicMessageType( + DynamicSerializationSupport::SharedPtr serialization_support, + std::shared_ptr rosidl_dynamic_type) +: DynamicType(serialization_support, rosidl_dynamic_type) {} + + +DynamicMessageType::DynamicMessageType( + DynamicSerializationSupport::SharedPtr serialization_support, + const rosidl_runtime_c__type_description__TypeDescription * description) +: DynamicType(serialization_support, description) {} diff --git a/rclcpp/src/rclcpp/dynamic_typesupport/dynamic_serialization_support.cpp b/rclcpp/src/rclcpp/dynamic_typesupport/dynamic_serialization_support.cpp new file mode 100644 index 0000000000..4c7d90ebde --- /dev/null +++ b/rclcpp/src/rclcpp/dynamic_typesupport/dynamic_serialization_support.cpp @@ -0,0 +1,131 @@ +// Copyright 2023 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include + +#include "rclcpp/dynamic_typesupport/dynamic_serialization_support.hpp" +#include "rclcpp/exceptions.hpp" +#include "rcutils/logging_macros.h" +#include "rmw/dynamic_typesupport.h" + +#include + +using rclcpp::dynamic_typesupport::DynamicSerializationSupport; + +// CONSTRUCTION ==================================================================================== +DynamicSerializationSupport::DynamicSerializationSupport( + const std::string & serialization_library_name) +: rosidl_serialization_support_(nullptr) +{ + rosidl_dynamic_typesupport_serialization_support_t * rosidl_serialization_support = nullptr; + + if (serialization_library_name.empty()) { + rosidl_serialization_support = rmw_get_serialization_support(NULL); + } else { + rosidl_serialization_support = + rmw_get_serialization_support(serialization_library_name.c_str()); + } + + if (!rosidl_serialization_support) { + throw std::runtime_error("could not create new serialization support object"); + } + + rosidl_serialization_support_.reset( + rosidl_serialization_support, + // Custom deleter + [](rosidl_dynamic_typesupport_serialization_support_t * rosidl_serialization_support) -> void { + rosidl_dynamic_typesupport_serialization_support_fini(rosidl_serialization_support); + free(rosidl_serialization_support); + }); +} + + +DynamicSerializationSupport::DynamicSerializationSupport( + rosidl_dynamic_typesupport_serialization_support_t * rosidl_serialization_support) +: rosidl_serialization_support_(nullptr) +{ + if (!rosidl_serialization_support) { + throw std::runtime_error("serialization support cannot be nullptr!"); + } + + // Custom deleter + rosidl_serialization_support_.reset( + rosidl_serialization_support, + [](rosidl_dynamic_typesupport_serialization_support_t * rosidl_serialization_support) -> void { + rosidl_dynamic_typesupport_serialization_support_fini(rosidl_serialization_support); + free(rosidl_serialization_support); + }); +} + + +DynamicSerializationSupport::DynamicSerializationSupport( + std::shared_ptr rosidl_serialization_support) +: rosidl_serialization_support_(rosidl_serialization_support) {} + + +DynamicSerializationSupport::DynamicSerializationSupport( + DynamicSerializationSupport && other) noexcept +: rosidl_serialization_support_(std::exchange(other.rosidl_serialization_support_, nullptr)) {} + + +DynamicSerializationSupport & +DynamicSerializationSupport::operator=(DynamicSerializationSupport && other) noexcept +{ + std::swap(rosidl_serialization_support_, other.rosidl_serialization_support_); + return *this; +} + + +DynamicSerializationSupport::~DynamicSerializationSupport() {} + + +// GETTERS ========================================================================================= +const std::string +DynamicSerializationSupport::get_library_identifier() const +{ + return std::string( + rosidl_dynamic_typesupport_serialization_support_get_library_identifier( + rosidl_serialization_support_.get())); +} + + +rosidl_dynamic_typesupport_serialization_support_t * +DynamicSerializationSupport::get_rosidl_serialization_support() +{ + return rosidl_serialization_support_.get(); +} + + +const rosidl_dynamic_typesupport_serialization_support_t * +DynamicSerializationSupport::get_rosidl_serialization_support() const +{ + return rosidl_serialization_support_.get(); +} + + +std::shared_ptr +DynamicSerializationSupport::get_shared_rosidl_serialization_support() +{ + return std::shared_ptr( + shared_from_this(), rosidl_serialization_support_.get()); +} + + +std::shared_ptr +DynamicSerializationSupport::get_shared_rosidl_serialization_support() const +{ + return std::shared_ptr( + shared_from_this(), rosidl_serialization_support_.get()); +} diff --git a/rclcpp/src/rclcpp/dynamic_typesupport/dynamic_type.cpp b/rclcpp/src/rclcpp/dynamic_typesupport/dynamic_type.cpp new file mode 100644 index 0000000000..8590722edc --- /dev/null +++ b/rclcpp/src/rclcpp/dynamic_typesupport/dynamic_type.cpp @@ -0,0 +1,320 @@ +// Copyright 2023 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include + +#include "rclcpp/dynamic_typesupport/dynamic_data.hpp" +#include "rclcpp/dynamic_typesupport/dynamic_serialization_support.hpp" +#include "rclcpp/dynamic_typesupport/dynamic_type.hpp" +#include "rclcpp/dynamic_typesupport/dynamic_type_builder.hpp" +#include "rclcpp/exceptions.hpp" +#include "rcutils/logging_macros.h" + +#include +#include +#include + +using rclcpp::dynamic_typesupport::DynamicData; +using rclcpp::dynamic_typesupport::DynamicSerializationSupport; +using rclcpp::dynamic_typesupport::DynamicType; +using rclcpp::dynamic_typesupport::DynamicTypeBuilder; + + +// CONSTRUCTION ==================================================================================== +DynamicType::DynamicType(DynamicTypeBuilder::SharedPtr dynamic_type_builder) +: serialization_support_(dynamic_type_builder->get_shared_dynamic_serialization_support()), + rosidl_dynamic_type_(nullptr) +{ + if (!serialization_support_) { + throw std::runtime_error("dynamic type could not bind serialization support!"); + } + + rosidl_dynamic_typesupport_dynamic_type_builder_t * rosidl_dynamic_type_builder = + dynamic_type_builder->get_rosidl_dynamic_type_builder(); + if (!rosidl_dynamic_type_builder) { + throw std::runtime_error("dynamic type builder cannot be nullptr!"); + } + + rosidl_dynamic_typesupport_dynamic_type_t * rosidl_dynamic_type = nullptr; + rosidl_dynamic_type = rosidl_dynamic_typesupport_dynamic_type_init_from_dynamic_type_builder( + rosidl_dynamic_type_builder); + if (!rosidl_dynamic_type) { + throw std::runtime_error("could not create new dynamic type object"); + } + + rosidl_dynamic_type_.reset( + rosidl_dynamic_type, + // Custom deleter + [](rosidl_dynamic_typesupport_dynamic_type_t * rosidl_dynamic_type)->void { + rosidl_dynamic_typesupport_dynamic_type_fini(rosidl_dynamic_type); + free(rosidl_dynamic_type); + }); +} + + +DynamicType::DynamicType( + DynamicSerializationSupport::SharedPtr serialization_support, + rosidl_dynamic_typesupport_dynamic_type_t * rosidl_dynamic_type) +: serialization_support_(serialization_support), rosidl_dynamic_type_(nullptr) +{ + if (!rosidl_dynamic_type) { + throw std::runtime_error("rosidl dynamic type cannot be nullptr!"); + } + if (serialization_support) { + if (!match_serialization_support_(*serialization_support, *rosidl_dynamic_type)) { + throw std::runtime_error( + "serialization support library identifier does not match dynamic type's!"); + } + } + + rosidl_dynamic_type_.reset( + rosidl_dynamic_type, + // Custom deleter + [](rosidl_dynamic_typesupport_dynamic_type_t * rosidl_dynamic_type)->void { + rosidl_dynamic_typesupport_dynamic_type_fini(rosidl_dynamic_type); + free(rosidl_dynamic_type); + }); +} + + +DynamicType::DynamicType( + DynamicSerializationSupport::SharedPtr serialization_support, + std::shared_ptr rosidl_dynamic_type) +: serialization_support_(serialization_support), rosidl_dynamic_type_(rosidl_dynamic_type) +{ + if (!rosidl_dynamic_type) { + throw std::runtime_error("rosidl dynamic type cannot be nullptr!"); + } + if (serialization_support) { + if (!match_serialization_support_(*serialization_support, *rosidl_dynamic_type)) { + throw std::runtime_error( + "serialization support library identifier does not match dynamic type's!"); + } + } +} + + +DynamicType::DynamicType( + DynamicSerializationSupport::SharedPtr serialization_support, + const rosidl_runtime_c__type_description__TypeDescription * description) +: serialization_support_(serialization_support), rosidl_dynamic_type_(nullptr) +{ + init_from_description(description, serialization_support); +} + + +DynamicType::DynamicType(const DynamicType & other) +: enable_shared_from_this(), serialization_support_(nullptr), rosidl_dynamic_type_(nullptr) +{ + DynamicType out = other.clone(); + std::swap(serialization_support_, out.serialization_support_); + std::swap(rosidl_dynamic_type_, out.rosidl_dynamic_type_); +} + + +DynamicType::DynamicType(DynamicType && other) noexcept +: serialization_support_(std::exchange(other.serialization_support_, nullptr)), + rosidl_dynamic_type_(std::exchange(other.rosidl_dynamic_type_, nullptr)) {} + + +DynamicType & +DynamicType::operator=(const DynamicType & other) +{ + return *this = DynamicType(other); +} + + +DynamicType & +DynamicType::operator=(DynamicType && other) noexcept +{ + std::swap(serialization_support_, other.serialization_support_); + std::swap(rosidl_dynamic_type_, other.rosidl_dynamic_type_); + return *this; +} + + +DynamicType::~DynamicType() {} + + +void +DynamicType::init_from_description( + const rosidl_runtime_c__type_description__TypeDescription * description, + DynamicSerializationSupport::SharedPtr serialization_support) +{ + if (!description) { + throw std::runtime_error("description cannot be nullptr!"); + } + if (serialization_support) { + // Swap serialization support if serialization support is given + serialization_support_ = serialization_support; + } + + rosidl_dynamic_typesupport_dynamic_type_t * rosidl_dynamic_type = nullptr; + rosidl_dynamic_type = + rosidl_dynamic_typesupport_dynamic_type_init_from_description( + serialization_support_->get_rosidl_serialization_support(), description); + if (!rosidl_dynamic_type) { + throw std::runtime_error("could not create new dynamic type object"); + } + + rosidl_dynamic_type_.reset( + rosidl_dynamic_type, + // Custom deleter + [](rosidl_dynamic_typesupport_dynamic_type_t * rosidl_dynamic_type)->void { + rosidl_dynamic_typesupport_dynamic_type_fini(rosidl_dynamic_type); + free(rosidl_dynamic_type); + }); +} + + +bool +DynamicType::match_serialization_support_( + const DynamicSerializationSupport & serialization_support, + const rosidl_dynamic_typesupport_dynamic_type_t & rosidl_dynamic_type) +{ + bool out = true; + + if (serialization_support.get_library_identifier() != std::string( + rosidl_dynamic_type.serialization_support->library_identifier)) + { + RCUTILS_LOG_ERROR( + "serialization support library identifier does not match dynamic type's"); + out = false; + } + + // TODO(methylDragon): Can I do this?? Is it portable? + if (serialization_support.get_rosidl_serialization_support() != + rosidl_dynamic_type.serialization_support) + { + RCUTILS_LOG_ERROR( + "serialization support pointer does not match dynamic type's"); + out = false; + } + + return out; +} + + +// GETTERS ========================================================================================= +const std::string +DynamicType::get_library_identifier() const +{ + return std::string(rosidl_dynamic_type_->serialization_support->library_identifier); +} + + +const std::string +DynamicType::get_name() const +{ + size_t buf_length; + const char * buf = rosidl_dynamic_typesupport_dynamic_type_get_name( + get_rosidl_dynamic_type(), &buf_length); + return std::string(buf, buf_length); +} + + +size_t +DynamicType::get_member_count() const +{ + return rosidl_dynamic_typesupport_dynamic_type_get_member_count(rosidl_dynamic_type_.get()); +} + + +rosidl_dynamic_typesupport_dynamic_type_t * +DynamicType::get_rosidl_dynamic_type() +{ + return rosidl_dynamic_type_.get(); +} + + +const rosidl_dynamic_typesupport_dynamic_type_t * +DynamicType::get_rosidl_dynamic_type() const +{ + return rosidl_dynamic_type_.get(); +} + + +std::shared_ptr +DynamicType::get_shared_rosidl_dynamic_type() +{ + return std::shared_ptr( + shared_from_this(), rosidl_dynamic_type_.get()); +} + + +std::shared_ptr +DynamicType::get_shared_rosidl_dynamic_type() const +{ + return std::shared_ptr( + shared_from_this(), rosidl_dynamic_type_.get()); +} + + +DynamicSerializationSupport::SharedPtr +DynamicType::get_shared_dynamic_serialization_support() +{ + return serialization_support_; +} + + +std::shared_ptr +DynamicType::get_shared_dynamic_serialization_support() const +{ + return serialization_support_; +} + + +// METHODS ========================================================================================= +DynamicType +DynamicType::clone() const +{ + return DynamicType( + serialization_support_, + rosidl_dynamic_typesupport_dynamic_type_clone(get_rosidl_dynamic_type())); +} + + +DynamicType::SharedPtr +DynamicType::clone_shared() const +{ + return DynamicType::make_shared( + serialization_support_, + rosidl_dynamic_typesupport_dynamic_type_clone(get_rosidl_dynamic_type())); +} + + +bool +DynamicType::equals(const DynamicType & other) const +{ + if (get_library_identifier() != other.get_library_identifier()) { + throw std::runtime_error("library identifiers don't match"); + } + return rosidl_dynamic_typesupport_dynamic_type_equals( + get_rosidl_dynamic_type(), other.get_rosidl_dynamic_type()); +} + + +DynamicData +DynamicType::build_data() +{ + return DynamicData(shared_from_this()); +} + + +DynamicData::SharedPtr +DynamicType::build_data_shared() +{ + return DynamicData::make_shared(shared_from_this()); +} diff --git a/rclcpp/src/rclcpp/dynamic_typesupport/dynamic_type_builder.cpp b/rclcpp/src/rclcpp/dynamic_typesupport/dynamic_type_builder.cpp new file mode 100644 index 0000000000..18d23625a1 --- /dev/null +++ b/rclcpp/src/rclcpp/dynamic_typesupport/dynamic_type_builder.cpp @@ -0,0 +1,492 @@ +// Copyright 2023 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include + +#include "rclcpp/dynamic_typesupport/dynamic_data.hpp" +#include "rclcpp/dynamic_typesupport/dynamic_serialization_support.hpp" +#include "rclcpp/dynamic_typesupport/dynamic_type.hpp" +#include "rclcpp/dynamic_typesupport/dynamic_type_builder.hpp" +#include "rclcpp/exceptions.hpp" +#include "rcutils/logging_macros.h" + +#include +#include +#include + +using rclcpp::dynamic_typesupport::DynamicData; +using rclcpp::dynamic_typesupport::DynamicSerializationSupport; +using rclcpp::dynamic_typesupport::DynamicType; +using rclcpp::dynamic_typesupport::DynamicTypeBuilder; + + +#ifndef RCLCPP__DYNAMIC_TYPESUPPORT__DETAIL__DYNAMIC_TYPE_BUILDER_IMPL_HPP_ +// Template specialization implementations +#include "rclcpp/dynamic_typesupport/detail/dynamic_type_builder_impl.hpp" +#endif + + +// CONSTRUCTION ================================================================================== +DynamicTypeBuilder::DynamicTypeBuilder( + DynamicSerializationSupport::SharedPtr serialization_support, const std::string & name) +: serialization_support_(serialization_support), rosidl_dynamic_type_builder_(nullptr) +{ + init_from_serialization_support_(serialization_support, name); + if (!rosidl_dynamic_type_builder_) { + throw std::runtime_error("could not create new dynamic type builder object"); + } +} + + +DynamicTypeBuilder::DynamicTypeBuilder( + DynamicSerializationSupport::SharedPtr serialization_support, + rosidl_dynamic_typesupport_dynamic_type_builder_t * rosidl_dynamic_type_builder) +: serialization_support_(serialization_support), rosidl_dynamic_type_builder_(nullptr) +{ + if (!serialization_support) { + throw std::runtime_error("serialization support cannot be nullptr!"); + } + if (!rosidl_dynamic_type_builder) { + throw std::runtime_error("rosidl dynamic type builder cannot be nullptr!"); + } + if (!match_serialization_support_(*serialization_support, *rosidl_dynamic_type_builder)) { + throw std::runtime_error( + "serialization support library does not match dynamic type builder's!"); + } + + rosidl_dynamic_type_builder_.reset( + rosidl_dynamic_type_builder, + // Custom deleter + [](rosidl_dynamic_typesupport_dynamic_type_builder_t * rosidl_dynamic_type_builder)->void { + rosidl_dynamic_typesupport_dynamic_type_builder_fini(rosidl_dynamic_type_builder); + free(rosidl_dynamic_type_builder); + }); +} + + +DynamicTypeBuilder::DynamicTypeBuilder( + DynamicSerializationSupport::SharedPtr serialization_support, + std::shared_ptr rosidl_dynamic_type_builder) +: serialization_support_(serialization_support), + rosidl_dynamic_type_builder_(rosidl_dynamic_type_builder) +{ + if (!serialization_support) { + throw std::runtime_error("serialization support cannot be nullptr!"); + } + if (!rosidl_dynamic_type_builder) { + throw std::runtime_error("rosidl dynamic type builder cannot be nullptr!"); + } + if (!match_serialization_support_(*serialization_support, *rosidl_dynamic_type_builder.get())) { + throw std::runtime_error( + "serialization support library does not match dynamic type builder's!"); + } +} + + +DynamicTypeBuilder::DynamicTypeBuilder( + DynamicSerializationSupport::SharedPtr serialization_support, + const rosidl_runtime_c__type_description__TypeDescription * description) +: serialization_support_(serialization_support), + rosidl_dynamic_type_builder_(nullptr) +{ + if (!serialization_support) { + throw std::runtime_error("serialization support cannot be nullptr!"); + } + init_from_description(description, serialization_support); +} + + +DynamicTypeBuilder::DynamicTypeBuilder(const DynamicTypeBuilder & other) +: enable_shared_from_this(), serialization_support_(nullptr), rosidl_dynamic_type_builder_(nullptr) +{ + DynamicTypeBuilder out = other.clone(); + std::swap(serialization_support_, out.serialization_support_); + std::swap(rosidl_dynamic_type_builder_, out.rosidl_dynamic_type_builder_); +} + + +DynamicTypeBuilder::DynamicTypeBuilder(DynamicTypeBuilder && other) noexcept +: serialization_support_(std::exchange(other.serialization_support_, nullptr)), + rosidl_dynamic_type_builder_(std::exchange(other.rosidl_dynamic_type_builder_, nullptr)) {} + + +DynamicTypeBuilder & +DynamicTypeBuilder::operator=(const DynamicTypeBuilder & other) +{ + return *this = DynamicTypeBuilder(other); +} + + +DynamicTypeBuilder & +DynamicTypeBuilder::operator=(DynamicTypeBuilder && other) noexcept +{ + std::swap(serialization_support_, other.serialization_support_); + std::swap(rosidl_dynamic_type_builder_, other.rosidl_dynamic_type_builder_); + return *this; +} + + +DynamicTypeBuilder::~DynamicTypeBuilder() {} + + +void +DynamicTypeBuilder::init_from_description( + const rosidl_runtime_c__type_description__TypeDescription * description, + DynamicSerializationSupport::SharedPtr serialization_support) +{ + if (!description) { + throw std::runtime_error("description cannot be nullptr!"); + } + if (serialization_support) { + // Swap serialization support if serialization support is given + serialization_support_ = serialization_support; + } + + rosidl_dynamic_typesupport_dynamic_type_builder_t * rosidl_dynamic_type_builder = nullptr; + rosidl_dynamic_type_builder = + rosidl_dynamic_typesupport_dynamic_type_builder_init_from_description( + serialization_support_->get_rosidl_serialization_support(), description); + if (!rosidl_dynamic_type_builder) { + throw std::runtime_error("could not create new dynamic type builder object"); + } + + rosidl_dynamic_type_builder_.reset( + rosidl_dynamic_type_builder, + // Custom deleter + [](rosidl_dynamic_typesupport_dynamic_type_builder_t * rosidl_dynamic_type_builder)->void { + rosidl_dynamic_typesupport_dynamic_type_builder_fini(rosidl_dynamic_type_builder); + free(rosidl_dynamic_type_builder); + }); +} + + +void +DynamicTypeBuilder::init_from_serialization_support_( + DynamicSerializationSupport::SharedPtr serialization_support, + const std::string & name) +{ + if (!serialization_support) { + throw std::runtime_error("serialization support cannot be nullptr!"); + } + if (!serialization_support->get_rosidl_serialization_support()) { + throw std::runtime_error("serialization support raw pointer cannot be nullptr!"); + } + + + rosidl_dynamic_typesupport_dynamic_type_builder_t * rosidl_dynamic_type_builder = nullptr; + rosidl_dynamic_type_builder = rosidl_dynamic_typesupport_dynamic_type_builder_init( + serialization_support->get_rosidl_serialization_support(), name.c_str(), name.size()); + + if (!rosidl_dynamic_type_builder) { + throw std::runtime_error("could not create new dynamic type builder object"); + } + + rosidl_dynamic_type_builder_.reset( + rosidl_dynamic_type_builder, + // Custom deleter + [](rosidl_dynamic_typesupport_dynamic_type_builder_t * rosidl_dynamic_type_builder)->void { + rosidl_dynamic_typesupport_dynamic_type_builder_fini(rosidl_dynamic_type_builder); + free(rosidl_dynamic_type_builder); + }); +} + + +bool +DynamicTypeBuilder::match_serialization_support_( + const DynamicSerializationSupport & serialization_support, + const rosidl_dynamic_typesupport_dynamic_type_builder_t & rosidl_dynamic_type_builder) +{ + bool out = true; + + if (serialization_support.get_library_identifier() != std::string( + rosidl_dynamic_type_builder.serialization_support->library_identifier)) + { + RCUTILS_LOG_ERROR( + "serialization support library identifier does not match dynamic type builder's"); + out = false; + } + + // TODO(methylDragon): Can I do this?? Is it portable? + if (serialization_support.get_rosidl_serialization_support() != + rosidl_dynamic_type_builder.serialization_support) + { + RCUTILS_LOG_ERROR( + "serialization support pointer does not match dynamic type builder's"); + out = false; + } + + return out; +} + + +// GETTERS ======================================================================================= +const std::string +DynamicTypeBuilder::get_library_identifier() const +{ + return std::string(rosidl_dynamic_type_builder_->serialization_support->library_identifier); +} + + +const std::string +DynamicTypeBuilder::get_name() const +{ + size_t buf_length; + const char * buf = rosidl_dynamic_typesupport_dynamic_type_builder_get_name( + get_rosidl_dynamic_type_builder(), &buf_length); + return std::string(buf, buf_length); +} + + +rosidl_dynamic_typesupport_dynamic_type_builder_t * +DynamicTypeBuilder::get_rosidl_dynamic_type_builder() +{ + return rosidl_dynamic_type_builder_.get(); +} + + +const rosidl_dynamic_typesupport_dynamic_type_builder_t * +DynamicTypeBuilder::get_rosidl_dynamic_type_builder() const +{ + return rosidl_dynamic_type_builder_.get(); +} + + +std::shared_ptr +DynamicTypeBuilder::get_shared_rosidl_dynamic_type_builder() +{ + return std::shared_ptr( + shared_from_this(), rosidl_dynamic_type_builder_.get()); +} + + +std::shared_ptr +DynamicTypeBuilder::get_shared_rosidl_dynamic_type_builder() const +{ + return std::shared_ptr( + shared_from_this(), rosidl_dynamic_type_builder_.get()); +} + + +DynamicSerializationSupport::SharedPtr +DynamicTypeBuilder::get_shared_dynamic_serialization_support() +{ + return serialization_support_; +} + + +std::shared_ptr +DynamicTypeBuilder::get_shared_dynamic_serialization_support() const +{ + return serialization_support_; +} + + +// METHODS ======================================================================================= +void +DynamicTypeBuilder::set_name(const std::string & name) +{ + rosidl_dynamic_typesupport_dynamic_type_builder_set_name( + get_rosidl_dynamic_type_builder(), name.c_str(), name.size()); +} + + +DynamicTypeBuilder +DynamicTypeBuilder::clone() const +{ + return DynamicTypeBuilder( + serialization_support_, + rosidl_dynamic_typesupport_dynamic_type_builder_clone(get_rosidl_dynamic_type_builder())); +} + + +DynamicTypeBuilder::SharedPtr +DynamicTypeBuilder::clone_shared() const +{ + return DynamicTypeBuilder::make_shared( + serialization_support_, + rosidl_dynamic_typesupport_dynamic_type_builder_clone(get_rosidl_dynamic_type_builder())); +} + + +void +DynamicTypeBuilder::clear() +{ + if (!serialization_support_) { + throw std::runtime_error( + "cannot call clear() on a dynamic type builder with uninitialized serialization support"); + } + + const std::string & name = get_name(); + init_from_serialization_support_(serialization_support_, name); + if (!rosidl_dynamic_type_builder_) { + throw std::runtime_error("could not create new dynamic type builder object"); + } +} + + +DynamicData +DynamicTypeBuilder::build_data() +{ + return DynamicData(shared_from_this()); +} + + +DynamicData::SharedPtr +DynamicTypeBuilder::build_data_shared() +{ + return DynamicData::make_shared(shared_from_this()); +} + + +DynamicType +DynamicTypeBuilder::build_type() +{ + return DynamicType(shared_from_this()); +} + + +DynamicType::SharedPtr +DynamicTypeBuilder::build_type_shared() +{ + return DynamicType::make_shared(shared_from_this()); +} + + +// ADD MEMBERS ===================================================================================== +// Defined in "detail/dynamic_type_builder_impl.hpp" + + +// ADD BOUNDED STRING MEMBERS ====================================================================== +void +DynamicTypeBuilder::add_bounded_string_member( + rosidl_dynamic_typesupport_member_id_t id, const std::string & name, size_t string_bound) +{ + rosidl_dynamic_typesupport_dynamic_type_builder_add_bounded_string_member( + get_rosidl_dynamic_type_builder(), id, name.c_str(), name.size(), string_bound); +} + + +void +DynamicTypeBuilder::add_bounded_wstring_member( + rosidl_dynamic_typesupport_member_id_t id, const std::string & name, size_t wstring_bound) +{ + rosidl_dynamic_typesupport_dynamic_type_builder_add_bounded_wstring_member( + get_rosidl_dynamic_type_builder(), id, name.c_str(), name.size(), wstring_bound); +} + + +void +DynamicTypeBuilder::add_bounded_string_array_member( + rosidl_dynamic_typesupport_member_id_t id, const std::string & name, + size_t string_bound, size_t array_length) +{ + rosidl_dynamic_typesupport_dynamic_type_builder_add_bounded_string_array_member( + get_rosidl_dynamic_type_builder(), id, name.c_str(), name.size(), string_bound, array_length); +} + + +void +DynamicTypeBuilder::add_bounded_wstring_array_member( + rosidl_dynamic_typesupport_member_id_t id, const std::string & name, + size_t wstring_bound, size_t array_length) +{ + rosidl_dynamic_typesupport_dynamic_type_builder_add_bounded_wstring_array_member( + get_rosidl_dynamic_type_builder(), id, name.c_str(), name.size(), wstring_bound, array_length); +} + + +void +DynamicTypeBuilder::add_bounded_string_unbounded_sequence_member( + rosidl_dynamic_typesupport_member_id_t id, const std::string & name, size_t string_bound) +{ + rosidl_dynamic_typesupport_dynamic_type_builder_add_bounded_string_unbounded_sequence_member( + get_rosidl_dynamic_type_builder(), id, name.c_str(), name.size(), string_bound); +} + + +void +DynamicTypeBuilder::add_bounded_wstring_unbounded_sequence_member( + rosidl_dynamic_typesupport_member_id_t id, const std::string & name, size_t wstring_bound) +{ + rosidl_dynamic_typesupport_dynamic_type_builder_add_bounded_wstring_unbounded_sequence_member( + get_rosidl_dynamic_type_builder(), id, name.c_str(), name.size(), wstring_bound); +} + + +void +DynamicTypeBuilder::add_bounded_string_bounded_sequence_member( + rosidl_dynamic_typesupport_member_id_t id, const std::string & name, + size_t string_bound, size_t sequence_bound) +{ + rosidl_dynamic_typesupport_dynamic_type_builder_add_bounded_string_bounded_sequence_member( + get_rosidl_dynamic_type_builder(), id, name.c_str(), name.size(), + string_bound, sequence_bound); +} + + +void +DynamicTypeBuilder::add_bounded_wstring_bounded_sequence_member( + rosidl_dynamic_typesupport_member_id_t id, const std::string & name, + size_t wstring_bound, size_t sequence_bound) +{ + rosidl_dynamic_typesupport_dynamic_type_builder_add_bounded_wstring_bounded_sequence_member( + get_rosidl_dynamic_type_builder(), id, name.c_str(), name.size(), + wstring_bound, sequence_bound); +} + + +// ADD NESTED MEMBERS ============================================================================== +void +DynamicTypeBuilder::add_complex_member( + rosidl_dynamic_typesupport_member_id_t id, const std::string & name, + DynamicType & nested_type) +{ + rosidl_dynamic_typesupport_dynamic_type_builder_add_complex_member( + get_rosidl_dynamic_type_builder(), id, name.c_str(), name.size(), + nested_type.get_rosidl_dynamic_type()); +} + + +void +DynamicTypeBuilder::add_complex_array_member( + rosidl_dynamic_typesupport_member_id_t id, const std::string & name, + DynamicType & nested_type, size_t array_length) +{ + rosidl_dynamic_typesupport_dynamic_type_builder_add_complex_array_member( + get_rosidl_dynamic_type_builder(), id, name.c_str(), name.size(), + nested_type.get_rosidl_dynamic_type(), array_length); +} + + +void +DynamicTypeBuilder::add_complex_unbounded_sequence_member( + rosidl_dynamic_typesupport_member_id_t id, const std::string & name, + DynamicType & nested_type) +{ + rosidl_dynamic_typesupport_dynamic_type_builder_add_complex_unbounded_sequence_member( + get_rosidl_dynamic_type_builder(), id, name.c_str(), name.size(), + nested_type.get_rosidl_dynamic_type()); +} + + +void +DynamicTypeBuilder::add_complex_bounded_sequence_member( + rosidl_dynamic_typesupport_member_id_t id, const std::string & name, + DynamicType & nested_type, size_t sequence_bound) +{ + rosidl_dynamic_typesupport_dynamic_type_builder_add_complex_bounded_sequence_member( + get_rosidl_dynamic_type_builder(), id, name.c_str(), name.size(), + nested_type.get_rosidl_dynamic_type(), sequence_bound); +} From d10e6b279e98736fe7078fae85d5bedb0ce66403 Mon Sep 17 00:00:00 2001 From: methylDragon Date: Mon, 20 Mar 2023 18:09:46 -0700 Subject: [PATCH 2/5] Implement dynamic message type support wrapper Signed-off-by: methylDragon --- rclcpp/CMakeLists.txt | 1 + .../dynamic_typesupport/dynamic_data.hpp | 2 +- .../dynamic_typesupport/dynamic_message.hpp | 4 +- .../dynamic_message_type.hpp | 2 +- .../dynamic_message_type_support.hpp | 189 +++++++++ .../dynamic_typesupport/dynamic_type.hpp | 2 +- .../dynamic_type_builder.hpp | 2 +- rclcpp/include/rclcpp/rclcpp.hpp | 3 + .../dynamic_typesupport/dynamic_data.cpp | 2 +- .../dynamic_message_type_support.cpp | 399 ++++++++++++++++++ .../dynamic_typesupport/dynamic_type.cpp | 2 +- .../dynamic_type_builder.cpp | 2 +- 12 files changed, 601 insertions(+), 9 deletions(-) create mode 100644 rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message_type_support.hpp create mode 100644 rclcpp/src/rclcpp/dynamic_typesupport/dynamic_message_type_support.cpp diff --git a/rclcpp/CMakeLists.txt b/rclcpp/CMakeLists.txt index 583aeece44..cbeb0a17a0 100644 --- a/rclcpp/CMakeLists.txt +++ b/rclcpp/CMakeLists.txt @@ -52,6 +52,7 @@ set(${PROJECT_NAME}_SRCS src/rclcpp/dynamic_typesupport/dynamic_data.cpp src/rclcpp/dynamic_typesupport/dynamic_message.cpp src/rclcpp/dynamic_typesupport/dynamic_message_type.cpp + src/rclcpp/dynamic_typesupport/dynamic_message_type_support.cpp src/rclcpp/dynamic_typesupport/dynamic_serialization_support.cpp src/rclcpp/dynamic_typesupport/dynamic_type.cpp src/rclcpp/dynamic_typesupport/dynamic_type_builder.cpp diff --git a/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_data.hpp b/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_data.hpp index 9429cac90f..452cdbc17a 100644 --- a/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_data.hpp +++ b/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_data.hpp @@ -143,7 +143,7 @@ class DynamicData : public std::enable_shared_from_this get_shared_dynamic_serialization_support(); RCLCPP_PUBLIC - std::shared_ptr + DynamicSerializationSupport::ConstSharedPtr get_shared_dynamic_serialization_support() const; RCLCPP_PUBLIC diff --git a/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message.hpp b/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message.hpp index d39fae07e1..0970bd7dc8 100644 --- a/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message.hpp +++ b/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message.hpp @@ -63,11 +63,11 @@ class DynamicMessage final : public DynamicData /// Construct a new DynamicMessage with the provided dynamic type builder RCLCPP_PUBLIC - explicit DynamicMessage(std::shared_ptr dynamic_type_builder); + explicit DynamicMessage(DynamicTypeBuilder::SharedPtr dynamic_type_builder); /// Construct a new DynamicMessage with the provided dynamic type RCLCPP_PUBLIC - explicit DynamicMessage(std::shared_ptr dynamic_type); + explicit DynamicMessage(DynamicType::SharedPtr dynamic_type); /// Assume ownership of raw pointer RCLCPP_PUBLIC diff --git a/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message_type.hpp b/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message_type.hpp index fd33180675..2379baa686 100644 --- a/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message_type.hpp +++ b/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message_type.hpp @@ -61,7 +61,7 @@ class DynamicMessageType final : public DynamicType /// Construct a new DynamicType with the provided dynamic type builder RCLCPP_PUBLIC - explicit DynamicMessageType(std::shared_ptr dynamic_type_builder); + explicit DynamicMessageType(DynamicTypeBuilder::SharedPtr dynamic_type_builder); /// Assume ownership of raw pointer RCLCPP_PUBLIC diff --git a/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message_type_support.hpp b/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message_type_support.hpp new file mode 100644 index 0000000000..149ad81bb7 --- /dev/null +++ b/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message_type_support.hpp @@ -0,0 +1,189 @@ +// Copyright 2023 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef RCLCPP__DYNAMIC_TYPESUPPORT__DYNAMIC_MESSAGE_TYPE_SUPPORT_HPP_ +#define RCLCPP__DYNAMIC_TYPESUPPORT__DYNAMIC_MESSAGE_TYPE_SUPPORT_HPP_ + +#include +#include + +#include "rclcpp/dynamic_typesupport/dynamic_message_type.hpp" +#include "rclcpp/dynamic_typesupport/dynamic_message.hpp" +#include "rclcpp/dynamic_typesupport/dynamic_serialization_support.hpp" + +#include "rclcpp/macros.hpp" +#include "rclcpp/visibility_control.hpp" + +#include +#include +#include + +namespace rclcpp +{ +namespace dynamic_typesupport +{ + +/// Utility wrapper class for rosidl_message_type_support_t * containing managed +/// instances of the typesupport handle impl. +/** + * + * NOTE: This class is the recommended way to obtain the dynamic message type + * support struct, instead of rcl_get_dynamic_message_typesupport_handle, + * because this class will manage the lifetimes for you. + * + * Do NOT call rcl_dynamic_message_typesupport_handle_fini!! + * + * This class: + * - Manages the lifetime of the raw pointer. + * - Exposes getter methods to get the raw pointer and shared pointers + * - Stores shared pointers to wrapper classes that expose the underlying + * serialization support API + * + * Ownership: + * - This class, similarly to the rosidl_dynamic_typesupport_serialization_support_t, must outlive + * all downstream usages of the serialization support. + */ +class DynamicMessageTypeSupport : public std::enable_shared_from_this +{ +public: + RCLCPP_SMART_PTR_ALIASES_ONLY(DynamicMessageTypeSupport) + + // CONSTRUCTION ================================================================================== + /// From description + RCLCPP_PUBLIC + DynamicMessageTypeSupport( + rosidl_runtime_c__type_description__TypeDescription * description, + const std::string & serialization_library_name = nullptr); + + /// From description, for provided serialization support + RCLCPP_PUBLIC + DynamicMessageTypeSupport( + DynamicSerializationSupport::SharedPtr serialization_support, + rosidl_runtime_c__type_description__TypeDescription * description); + + /// Assume ownership of managed types + RCLCPP_PUBLIC + DynamicMessageTypeSupport( + DynamicSerializationSupport::SharedPtr serialization_support, + DynamicMessageType::SharedPtr dynamic_message_type, + DynamicMessage::SharedPtr dynamic_message, + rosidl_runtime_c__type_description__TypeDescription * description = nullptr); + + RCLCPP_PUBLIC + virtual ~DynamicMessageTypeSupport(); + + + // GETTERS ======================================================================================= + RCLCPP_PUBLIC + const std::string + get_library_identifier() const; + + RCLCPP_PUBLIC + rosidl_message_type_support_t * + get_rosidl_message_type_support(); + + RCLCPP_PUBLIC + const rosidl_message_type_support_t * + get_rosidl_message_type_support() const; + + RCLCPP_PUBLIC + std::shared_ptr + get_shared_rosidl_message_type_support(); + + RCLCPP_PUBLIC + std::shared_ptr + get_shared_rosidl_message_type_support() const; + + RCLCPP_PUBLIC + rosidl_runtime_c__type_description__TypeDescription * + get_rosidl_runtime_c_type_description(); + + RCLCPP_PUBLIC + const rosidl_runtime_c__type_description__TypeDescription * + get_rosidl_runtime_c_type_description() const; + + RCLCPP_PUBLIC + std::shared_ptr + get_shared_rosidl_runtime_c_type_description(); + + RCLCPP_PUBLIC + std::shared_ptr + get_shared_rosidl_runtime_c_type_description() const; + + RCLCPP_PUBLIC + DynamicSerializationSupport::SharedPtr + get_shared_dynamic_serialization_support(); + + RCLCPP_PUBLIC + DynamicSerializationSupport::ConstSharedPtr + get_shared_dynamic_serialization_support() const; + + RCLCPP_PUBLIC + DynamicMessageType::SharedPtr + get_shared_dynamic_message_type(); + + RCLCPP_PUBLIC + DynamicMessageType::ConstSharedPtr + get_shared_dynamic_message_type() const; + + RCLCPP_PUBLIC + DynamicMessage::SharedPtr + get_shared_dynamic_message(); + + RCLCPP_PUBLIC + DynamicMessage::ConstSharedPtr + get_shared_dynamic_message() const; + +protected: + RCLCPP_DISABLE_COPY(DynamicMessageTypeSupport) + + DynamicSerializationSupport::SharedPtr serialization_support_; + DynamicMessageType::SharedPtr dynamic_message_type_; + DynamicMessage::SharedPtr dynamic_message_; + std::shared_ptr description_; + + std::shared_ptr rosidl_message_type_support_; + +private: + RCLCPP_PUBLIC + DynamicMessageTypeSupport(); + + RCLCPP_PUBLIC + void + init_serialization_support_(const std::string & serialization_library_name); + + RCLCPP_PUBLIC + void + init_dynamic_message_type_( + DynamicSerializationSupport::SharedPtr serialization_support, + const rosidl_runtime_c__type_description__TypeDescription * description); + + RCLCPP_PUBLIC + void + init_dynamic_message_(DynamicType::SharedPtr dynamic_type); + + RCLCPP_PUBLIC + void + init_rosidl_message_type_support_( + DynamicSerializationSupport::SharedPtr serialization_support, + DynamicMessageType::SharedPtr dynamic_message_type, + DynamicMessage::SharedPtr dynamic_message, + const rosidl_runtime_c__type_description__TypeDescription * description); +}; + + +} // namespace dynamic_typesupport +} // namespace rclcpp + +#endif // RCLCPP__DYNAMIC_TYPESUPPORT__DYNAMIC_MESSAGE_TYPE_SUPPORT_HPP_ diff --git a/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_type.hpp b/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_type.hpp index e0d9660c22..d61cdf8196 100644 --- a/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_type.hpp +++ b/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_type.hpp @@ -142,7 +142,7 @@ class DynamicType : public std::enable_shared_from_this get_shared_dynamic_serialization_support(); RCLCPP_PUBLIC - std::shared_ptr + DynamicSerializationSupport::ConstSharedPtr get_shared_dynamic_serialization_support() const; diff --git a/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_type_builder.hpp b/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_type_builder.hpp index 62199c838a..5e3dbaeb0f 100644 --- a/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_type_builder.hpp +++ b/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_type_builder.hpp @@ -140,7 +140,7 @@ class DynamicTypeBuilder : public std::enable_shared_from_this + DynamicSerializationSupport::ConstSharedPtr get_shared_dynamic_serialization_support() const; diff --git a/rclcpp/include/rclcpp/rclcpp.hpp b/rclcpp/include/rclcpp/rclcpp.hpp index ab4b54a0dd..d84610d159 100644 --- a/rclcpp/include/rclcpp/rclcpp.hpp +++ b/rclcpp/include/rclcpp/rclcpp.hpp @@ -130,6 +130,9 @@ * - rclcpp/dynamic_typesupport/dynamic_serialization_support.hpp * - rclcpp/dynamic_typesupport/dynamic_type_builder.hpp * - rclcpp/dynamic_typesupport/dynamic_type.hpp + * - Dynamic typesupport + * - rclcpp::dynamic_typesupport::DynamicMessageTypeSupport + * - rclcpp/dynamic_typesupport/dynamic_message_type_support.hpp * - Generic publisher * - rclcpp::Node::create_generic_publisher() * - rclcpp::GenericPublisher diff --git a/rclcpp/src/rclcpp/dynamic_typesupport/dynamic_data.cpp b/rclcpp/src/rclcpp/dynamic_typesupport/dynamic_data.cpp index f953e44a80..d1715b8087 100644 --- a/rclcpp/src/rclcpp/dynamic_typesupport/dynamic_data.cpp +++ b/rclcpp/src/rclcpp/dynamic_typesupport/dynamic_data.cpp @@ -303,7 +303,7 @@ DynamicData::get_shared_dynamic_serialization_support() } -std::shared_ptr +DynamicSerializationSupport::ConstSharedPtr DynamicData::get_shared_dynamic_serialization_support() const { return serialization_support_; diff --git a/rclcpp/src/rclcpp/dynamic_typesupport/dynamic_message_type_support.cpp b/rclcpp/src/rclcpp/dynamic_typesupport/dynamic_message_type_support.cpp new file mode 100644 index 0000000000..ada02b90d3 --- /dev/null +++ b/rclcpp/src/rclcpp/dynamic_typesupport/dynamic_message_type_support.cpp @@ -0,0 +1,399 @@ +// Copyright 2023 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include + +#include "rmw/dynamic_typesupport.h" + +#include "rclcpp/dynamic_typesupport/dynamic_message_type_support.hpp" + +#include "rclcpp/dynamic_typesupport/dynamic_message_type.hpp" +#include "rclcpp/dynamic_typesupport/dynamic_message.hpp" +#include "rclcpp/dynamic_typesupport/dynamic_serialization_support.hpp" +#include "rclcpp/exceptions.hpp" +#include "rclcpp/macros.hpp" +#include "rclcpp/visibility_control.hpp" +#include "rcutils/logging_macros.h" + +#include +#include +#include +#include + +using rclcpp::dynamic_typesupport::DynamicSerializationSupport; +using rclcpp::dynamic_typesupport::DynamicMessage; +using rclcpp::dynamic_typesupport::DynamicMessageType; +using rclcpp::dynamic_typesupport::DynamicMessageTypeSupport; + + +// CONSTRUCTION ==================================================================================== +DynamicMessageTypeSupport::DynamicMessageTypeSupport( + rosidl_runtime_c__type_description__TypeDescription * description, + const std::string & serialization_library_name) +: serialization_support_(nullptr), + dynamic_message_type_(nullptr), + dynamic_message_(nullptr), + description_(nullptr), + rosidl_message_type_support_(nullptr) +{ + if (!description) { + throw std::runtime_error("description cannot be nullptr!"); + } + description_.reset( + description, + [](rosidl_runtime_c__type_description__TypeDescription * description) -> void { + rosidl_runtime_c__type_description__TypeDescription__destroy(description); + }); + + init_serialization_support_(serialization_library_name); + if (!serialization_support_) { + throw std::runtime_error("could not init dynamic serialization support!"); + } + + init_dynamic_message_type_(serialization_support_, description); + if (!dynamic_message_type_) { + throw std::runtime_error("could not init dynamic message type!"); + } + + init_dynamic_message_(dynamic_message_type_); + if (!dynamic_message_) { + throw std::runtime_error("could not init dynamic message!"); + } + + init_rosidl_message_type_support_( + serialization_support_, dynamic_message_type_, dynamic_message_, description_.get()); + if (!rosidl_message_type_support_) { + throw std::runtime_error("could not init rosidl message type support!"); + } +} + + +DynamicMessageTypeSupport::DynamicMessageTypeSupport( + DynamicSerializationSupport::SharedPtr serialization_support, + rosidl_runtime_c__type_description__TypeDescription * description) +: serialization_support_(serialization_support), + dynamic_message_type_(nullptr), + dynamic_message_(nullptr), + description_(nullptr), + rosidl_message_type_support_(nullptr) +{ + // Check null + if (!serialization_support) { + throw std::runtime_error("serialization_support cannot be nullptr!"); + } + if (!description) { + throw std::runtime_error("description cannot be nullptr!"); + } + description_.reset( + description, + [](rosidl_runtime_c__type_description__TypeDescription * description) -> void { + rosidl_runtime_c__type_description__TypeDescription__destroy(description); + }); + + // Init + init_dynamic_message_type_(serialization_support_, description); + if (!dynamic_message_type_) { + throw std::runtime_error("could not init dynamic message type!"); + } + + init_dynamic_message_(dynamic_message_type_); + if (!dynamic_message_) { + throw std::runtime_error("could not init dynamic message!"); + } + + init_rosidl_message_type_support_( + serialization_support_, dynamic_message_type_, dynamic_message_, description_.get()); + if (!rosidl_message_type_support_) { + throw std::runtime_error("could not init rosidl message type support!"); + } +} + + +DynamicMessageTypeSupport::DynamicMessageTypeSupport( + DynamicSerializationSupport::SharedPtr serialization_support, + DynamicMessageType::SharedPtr dynamic_message_type, + DynamicMessage::SharedPtr dynamic_message, + rosidl_runtime_c__type_description__TypeDescription * description) +: serialization_support_(serialization_support), + dynamic_message_type_(dynamic_message_type), + dynamic_message_(dynamic_message), + description_(nullptr), + rosidl_message_type_support_(nullptr) +{ + // Check null + if (!serialization_support) { + throw std::runtime_error("serialization_support cannot be nullptr!"); + } + if (!dynamic_message_type) { + throw std::runtime_error("dynamic_message_type cannot be nullptr!"); + } + if (!dynamic_message) { + throw std::runtime_error("dynamic_message cannot be nullptr!"); + } + + if (description) { + description_.reset( + description, + [](rosidl_runtime_c__type_description__TypeDescription * description) -> void { + rosidl_runtime_c__type_description__TypeDescription__destroy(description); + }); + } + + // Check identifiers + if (serialization_support->get_library_identifier() != + dynamic_message_type->get_library_identifier()) + { + throw std::runtime_error( + "serialization support library identifier does not match " + "dynamic message type library identifier!"); + } + if (dynamic_message_type->get_library_identifier() != dynamic_message->get_library_identifier()) { + throw std::runtime_error( + "dynamic message type library identifier does not match " + "dynamic message library identifier!"); + } + + // Check pointers + /* *INDENT-OFF* */ + if (serialization_support->get_rosidl_serialization_support() != + dynamic_message_type + ->get_shared_dynamic_serialization_support() + ->get_rosidl_serialization_support()) + { + throw std::runtime_error("serialization support pointer dynamic message type's"); + } + if (dynamic_message_type + ->get_shared_dynamic_serialization_support() + ->get_rosidl_serialization_support() != + dynamic_message_type + ->get_shared_dynamic_serialization_support() + ->get_rosidl_serialization_support()) + { + throw std::runtime_error("serialization support pointer dynamic message type's"); + } + /* *INDENT-ON* */ + + init_rosidl_message_type_support_( + serialization_support_, dynamic_message_type_, dynamic_message_, description_.get()); + if (!rosidl_message_type_support_) { + throw std::runtime_error("could not init rosidl message type support!"); + } +} + + +DynamicMessageTypeSupport::~DynamicMessageTypeSupport() {} + + +void +DynamicMessageTypeSupport::init_serialization_support_( + const std::string & serialization_library_name) +{ + serialization_support_ = DynamicSerializationSupport::make_shared(serialization_library_name); +} + + +void +DynamicMessageTypeSupport::init_dynamic_message_type_( + DynamicSerializationSupport::SharedPtr serialization_support, + const rosidl_runtime_c__type_description__TypeDescription * description) +{ + dynamic_message_type_ = DynamicMessageType::make_shared(serialization_support, description); +} + + +void +DynamicMessageTypeSupport::init_dynamic_message_(DynamicType::SharedPtr dynamic_type) +{ + dynamic_message_ = DynamicMessage::make_shared(dynamic_type); +} + + +void +DynamicMessageTypeSupport::init_rosidl_message_type_support_( + DynamicSerializationSupport::SharedPtr serialization_support, + DynamicMessageType::SharedPtr dynamic_message_type, + DynamicMessage::SharedPtr dynamic_message, + const rosidl_runtime_c__type_description__TypeDescription * description) +{ + bool middleware_supports_type_discovery = + rmw_feature_supported(RMW_MIDDLEWARE_SUPPORTS_TYPE_DISCOVERY); + bool middleware_can_take_dynamic_data = + rmw_feature_supported(RMW_MIDDLEWARE_CAN_TAKE_DYNAMIC_DATA); + + if (!middleware_supports_type_discovery && !description) { + RCUTILS_LOG_ERROR_NAMED( + rmw_dynamic_typesupport_c__identifier, + "Middleware does not support type discovery! Deferred dynamic type" + "message type support will never be populated! You must provide a type " + "description!"); + return; + } + + // NOTE(methylDragon): We don't finalize the rosidl_message_type_support->data since its members + // are they're managed by the passed in SharedPtr wrapper classes + rosidl_message_type_support_ = std::make_shared(); + + if (!rosidl_message_type_support_) { + RCUTILS_LOG_ERROR_NAMED( + rmw_dynamic_typesupport_c__identifier, + "Could not allocate rosidl_message_type_support_t struct"); + return; + } + + rosidl_message_type_support_->typesupport_identifier = rmw_dynamic_typesupport_c__identifier; + + // NOTE(methylDragon): To populate dynamic_type and description if deferred, OUTSIDE + rosidl_message_type_support_->data = calloc(1, sizeof(rmw_dynamic_typesupport_impl_t)); + if (!rosidl_message_type_support_->data) { + RCUTILS_LOG_ERROR_NAMED( + rmw_dynamic_typesupport_c__identifier, + "Could not allocate rmw_dynamic_typesupport_impl_t struct"); + rosidl_message_type_support_.reset(); + } + + rmw_dynamic_typesupport_impl_t * ts_impl = + (rmw_dynamic_typesupport_impl_t *)rosidl_message_type_support_->data; + + ts_impl->take_dynamic_data = middleware_can_take_dynamic_data; + ts_impl->serialization_support = serialization_support->get_rosidl_serialization_support(); + ts_impl->dynamic_type = dynamic_message_type->get_rosidl_dynamic_type(); + ts_impl->dynamic_data = dynamic_message->get_rosidl_dynamic_data(); + rosidl_message_type_support_->func = get_message_typesupport_handle_function; + + if (description) { + ts_impl->description = rosidl_runtime_c__type_description__TypeDescription__create(); + if (ts_impl->description == NULL) { + RCUTILS_LOG_ERROR_NAMED( + rmw_dynamic_typesupport_c__identifier, + "Could not create type description to assign into"); + rosidl_message_type_support_.reset(); + } + + if (!rosidl_runtime_c__type_description__TypeDescription__copy( + description, ts_impl->description)) + { + RCUTILS_LOG_ERROR_NAMED( + rmw_dynamic_typesupport_c__identifier, + "Could not copy type description"); + rosidl_message_type_support_.reset(); + } + } +} + + +// GETTERS ========================================================================================= +const std::string +DynamicMessageTypeSupport::get_library_identifier() const +{ + return serialization_support_->get_library_identifier(); +} + + +rosidl_message_type_support_t * +DynamicMessageTypeSupport::get_rosidl_message_type_support() +{ + return rosidl_message_type_support_.get(); +} + + +const rosidl_message_type_support_t * +DynamicMessageTypeSupport::get_rosidl_message_type_support() const +{ + return rosidl_message_type_support_.get(); +} + + +std::shared_ptr +DynamicMessageTypeSupport::get_shared_rosidl_message_type_support() +{ + return rosidl_message_type_support_; +} + + +std::shared_ptr +DynamicMessageTypeSupport::get_shared_rosidl_message_type_support() const +{ + return rosidl_message_type_support_; +} + + +rosidl_runtime_c__type_description__TypeDescription * +DynamicMessageTypeSupport::get_rosidl_runtime_c_type_description() +{ + return description_.get(); +} + + +const rosidl_runtime_c__type_description__TypeDescription * +DynamicMessageTypeSupport::get_rosidl_runtime_c_type_description() const +{ + return description_.get(); +} + + +std::shared_ptr +DynamicMessageTypeSupport::get_shared_rosidl_runtime_c_type_description() +{ + return description_; +} + + +std::shared_ptr +DynamicMessageTypeSupport::get_shared_rosidl_runtime_c_type_description() const +{ + return description_; +} + + +DynamicSerializationSupport::SharedPtr +DynamicMessageTypeSupport::get_shared_dynamic_serialization_support() +{ + return serialization_support_; +} + + +DynamicSerializationSupport::ConstSharedPtr +DynamicMessageTypeSupport::get_shared_dynamic_serialization_support() const +{ + return serialization_support_; +} + + +DynamicMessageType::SharedPtr +DynamicMessageTypeSupport::get_shared_dynamic_message_type() +{ + return dynamic_message_type_; +} + + +DynamicMessageType::ConstSharedPtr +DynamicMessageTypeSupport::get_shared_dynamic_message_type() const +{ + return dynamic_message_type_; +} + + +DynamicMessage::SharedPtr +DynamicMessageTypeSupport::get_shared_dynamic_message() +{ + return dynamic_message_; +} + + +DynamicMessage::ConstSharedPtr +DynamicMessageTypeSupport::get_shared_dynamic_message() const +{ + return dynamic_message_; +} diff --git a/rclcpp/src/rclcpp/dynamic_typesupport/dynamic_type.cpp b/rclcpp/src/rclcpp/dynamic_typesupport/dynamic_type.cpp index 8590722edc..a189d88d53 100644 --- a/rclcpp/src/rclcpp/dynamic_typesupport/dynamic_type.cpp +++ b/rclcpp/src/rclcpp/dynamic_typesupport/dynamic_type.cpp @@ -269,7 +269,7 @@ DynamicType::get_shared_dynamic_serialization_support() } -std::shared_ptr +DynamicSerializationSupport::ConstSharedPtr DynamicType::get_shared_dynamic_serialization_support() const { return serialization_support_; diff --git a/rclcpp/src/rclcpp/dynamic_typesupport/dynamic_type_builder.cpp b/rclcpp/src/rclcpp/dynamic_typesupport/dynamic_type_builder.cpp index 18d23625a1..5cec3d7904 100644 --- a/rclcpp/src/rclcpp/dynamic_typesupport/dynamic_type_builder.cpp +++ b/rclcpp/src/rclcpp/dynamic_typesupport/dynamic_type_builder.cpp @@ -286,7 +286,7 @@ DynamicTypeBuilder::get_shared_dynamic_serialization_support() } -std::shared_ptr +DynamicSerializationSupport::ConstSharedPtr DynamicTypeBuilder::get_shared_dynamic_serialization_support() const { return serialization_support_; From df964aa8580a892d0b804d15fe9ee5c765cbce5d Mon Sep 17 00:00:00 2001 From: methylDragon Date: Tue, 21 Mar 2023 11:13:53 -0700 Subject: [PATCH 3/5] Refine wrappers Signed-off-by: methylDragon --- rclcpp/CMakeLists.txt | 2 - .../dynamic_typesupport/dynamic_data.hpp | 5 +- .../dynamic_typesupport/dynamic_message.hpp | 99 ++++++++++--------- .../dynamic_message_type.hpp | 79 +++++++-------- .../dynamic_message_type_support.hpp | 2 +- .../dynamic_serialization_support.hpp | 2 +- .../dynamic_typesupport/dynamic_data.cpp | 11 +-- .../dynamic_typesupport/dynamic_message.cpp | 61 ------------ .../dynamic_message_type.cpp | 57 ----------- .../dynamic_serialization_support.cpp | 6 +- 10 files changed, 102 insertions(+), 222 deletions(-) delete mode 100644 rclcpp/src/rclcpp/dynamic_typesupport/dynamic_message.cpp delete mode 100644 rclcpp/src/rclcpp/dynamic_typesupport/dynamic_message_type.cpp diff --git a/rclcpp/CMakeLists.txt b/rclcpp/CMakeLists.txt index cbeb0a17a0..848fbec174 100644 --- a/rclcpp/CMakeLists.txt +++ b/rclcpp/CMakeLists.txt @@ -50,8 +50,6 @@ set(${PROJECT_NAME}_SRCS src/rclcpp/detail/utilities.cpp src/rclcpp/duration.cpp src/rclcpp/dynamic_typesupport/dynamic_data.cpp - src/rclcpp/dynamic_typesupport/dynamic_message.cpp - src/rclcpp/dynamic_typesupport/dynamic_message_type.cpp src/rclcpp/dynamic_typesupport/dynamic_message_type_support.cpp src/rclcpp/dynamic_typesupport/dynamic_serialization_support.cpp src/rclcpp/dynamic_typesupport/dynamic_type.cpp diff --git a/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_data.hpp b/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_data.hpp index 452cdbc17a..36a6de270a 100644 --- a/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_data.hpp +++ b/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_data.hpp @@ -23,6 +23,7 @@ #include "rclcpp/macros.hpp" #include "rclcpp/visibility_control.hpp" +#include #include @@ -222,11 +223,11 @@ class DynamicData : public std::enable_shared_from_this RCLCPP_PUBLIC bool - serialize(std::shared_ptr buffer); + serialize(rcl_serialized_message_t * buffer); RCLCPP_PUBLIC bool - deserialize(std::shared_ptr buffer); + deserialize(rcl_serialized_message_t * buffer); // MEMBER ACCESS TEMPLATES ======================================================================= diff --git a/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message.hpp b/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message.hpp index 0970bd7dc8..215a303ccb 100644 --- a/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message.hpp +++ b/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message.hpp @@ -34,7 +34,7 @@ namespace rclcpp namespace dynamic_typesupport { - +using DynamicMessageType = DynamicType; /// Thin wrapper around DynamicData object for message pubsub /** * This class: @@ -48,55 +48,56 @@ namespace dynamic_typesupport * - The DynamicSerializationSupport's rosidl_dynamic_typesupport_serialization_support_t pointer * must point to the same location in memory as the stored raw pointer! */ -class DynamicMessage final : public DynamicData -{ -public: - RCLCPP_SMART_PTR_ALIASES_ONLY(DynamicMessage) - - // CONSTRUCTION ================================================================================== - // Most constructors require a passed in DynamicSerializationSupport::SharedPtr, to extend the - // lifetime of the serialization support (if the constructor cannot otherwise get it from args). - // - // In cases where a dynamic data pointer is passed, the serialization support composed by - // the data should be the exact same object managed by the DynamicSerializationSupport, - // otherwise the lifetime management will not work properly. - - /// Construct a new DynamicMessage with the provided dynamic type builder - RCLCPP_PUBLIC - explicit DynamicMessage(DynamicTypeBuilder::SharedPtr dynamic_type_builder); - - /// Construct a new DynamicMessage with the provided dynamic type - RCLCPP_PUBLIC - explicit DynamicMessage(DynamicType::SharedPtr dynamic_type); - - /// Assume ownership of raw pointer - RCLCPP_PUBLIC - DynamicMessage( - DynamicSerializationSupport::SharedPtr serialization_support, - rosidl_dynamic_typesupport_dynamic_data_t * rosidl_dynamic_data); - - /// Copy shared pointer - RCLCPP_PUBLIC - DynamicMessage( - DynamicSerializationSupport::SharedPtr serialization_support, - std::shared_ptr rosidl_dynamic_data); - - /// Loaning constructor - /// Must only be called with raw ptr obtained from loaning! - // NOTE(methylDragon): I'd put this in protected, but I need this exposed to - // enable_shared_from_this... - RCLCPP_PUBLIC - DynamicMessage( - DynamicData::SharedPtr parent_data, - rosidl_dynamic_typesupport_dynamic_data_t * rosidl_loaned_data); - - // NOTE(methylDragon): Deliberately no constructor from description to nudge users towards using - // construction from dynamic type/builder, which is more efficient -private: - RCLCPP_PUBLIC - DynamicMessage(); -}; +// class DynamicMessage final : public DynamicData +// { +// public: +// RCLCPP_SMART_PTR_ALIASES_ONLY(DynamicMessage) +// +// // CONSTRUCTION ================================================================================== +// // Most constructors require a passed in DynamicSerializationSupport::SharedPtr, to extend the +// // lifetime of the serialization support (if the constructor cannot otherwise get it from args). +// // +// // In cases where a dynamic data pointer is passed, the serialization support composed by +// // the data should be the exact same object managed by the DynamicSerializationSupport, +// // otherwise the lifetime management will not work properly. +// +// /// Construct a new DynamicMessage with the provided dynamic type builder +// RCLCPP_PUBLIC +// explicit DynamicMessage(DynamicTypeBuilder::SharedPtr dynamic_type_builder); +// +// /// Construct a new DynamicMessage with the provided dynamic type +// RCLCPP_PUBLIC +// explicit DynamicMessage(DynamicType::SharedPtr dynamic_type); +// +// /// Assume ownership of raw pointer +// RCLCPP_PUBLIC +// DynamicMessage( +// DynamicSerializationSupport::SharedPtr serialization_support, +// rosidl_dynamic_typesupport_dynamic_data_t * rosidl_dynamic_data); +// +// /// Copy shared pointer +// RCLCPP_PUBLIC +// DynamicMessage( +// DynamicSerializationSupport::SharedPtr serialization_support, +// std::shared_ptr rosidl_dynamic_data); +// +// /// Loaning constructor +// /// Must only be called with raw ptr obtained from loaning! +// // NOTE(methylDragon): I'd put this in protected, but I need this exposed to +// // enable_shared_from_this... +// RCLCPP_PUBLIC +// DynamicMessage( +// DynamicData::SharedPtr parent_data, +// rosidl_dynamic_typesupport_dynamic_data_t * rosidl_loaned_data); +// +// // NOTE(methylDragon): Deliberately no constructor from description to nudge users towards using +// // construction from dynamic type/builder, which is more efficient +// +// private: +// RCLCPP_PUBLIC +// DynamicMessage(); +// }; } // namespace dynamic_typesupport diff --git a/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message_type.hpp b/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message_type.hpp index 2379baa686..886a406864 100644 --- a/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message_type.hpp +++ b/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message_type.hpp @@ -33,6 +33,7 @@ namespace dynamic_typesupport { +using DynamicMessage = DynamicData; /// Thin wrapper around DynamicType object for message pubsub type representation /** * This class: @@ -46,45 +47,45 @@ namespace dynamic_typesupport * - The DynamicSerializationSupport's rosidl_dynamic_typesupport_serialization_support_t pointer * must point to the same location in memory as the stored raw pointer! */ -class DynamicMessageType final : public DynamicType -{ -public: - RCLCPP_SMART_PTR_ALIASES_ONLY(DynamicMessageType) - - // CONSTRUCTION ================================================================================== - // Most constructors require a passed in DynamicSerializationSupport::SharedPtr, to extend the - // lifetime of the serialization support (if the constructor cannot otherwise get it from args). - // - // In cases where a dynamic type pointer is passed, the serialization support composed by - // the type should be the exact same object managed by the DynamicSerializationSupport, - // otherwise the lifetime management will not work properly. - - /// Construct a new DynamicType with the provided dynamic type builder - RCLCPP_PUBLIC - explicit DynamicMessageType(DynamicTypeBuilder::SharedPtr dynamic_type_builder); - - /// Assume ownership of raw pointer - RCLCPP_PUBLIC - DynamicMessageType( - DynamicSerializationSupport::SharedPtr serialization_support, - rosidl_dynamic_typesupport_dynamic_type_t * rosidl_dynamic_type); - - /// Copy shared pointer - RCLCPP_PUBLIC - DynamicMessageType( - DynamicSerializationSupport::SharedPtr serialization_support, - std::shared_ptr rosidl_dynamic_type); - - /// From description - RCLCPP_PUBLIC - DynamicMessageType( - DynamicSerializationSupport::SharedPtr serialization_support, - const rosidl_runtime_c__type_description__TypeDescription * description); - -private: - RCLCPP_PUBLIC - DynamicMessageType(); -}; +// class DynamicMessageType final : public DynamicType +// { +// public: +// RCLCPP_SMART_PTR_ALIASES_ONLY(DynamicMessageType) +// +// // CONSTRUCTION ================================================================================== +// // Most constructors require a passed in DynamicSerializationSupport::SharedPtr, to extend the +// // lifetime of the serialization support (if the constructor cannot otherwise get it from args). +// // +// // In cases where a dynamic type pointer is passed, the serialization support composed by +// // the type should be the exact same object managed by the DynamicSerializationSupport, +// // otherwise the lifetime management will not work properly. +// +// /// Construct a new DynamicType with the provided dynamic type builder +// RCLCPP_PUBLIC +// explicit DynamicMessageType(DynamicTypeBuilder::SharedPtr dynamic_type_builder); +// +// /// Assume ownership of raw pointer +// RCLCPP_PUBLIC +// DynamicMessageType( +// DynamicSerializationSupport::SharedPtr serialization_support, +// rosidl_dynamic_typesupport_dynamic_type_t * rosidl_dynamic_type); +// +// /// Copy shared pointer +// RCLCPP_PUBLIC +// DynamicMessageType( +// DynamicSerializationSupport::SharedPtr serialization_support, +// std::shared_ptr rosidl_dynamic_type); +// +// /// From description +// RCLCPP_PUBLIC +// DynamicMessageType( +// DynamicSerializationSupport::SharedPtr serialization_support, +// const rosidl_runtime_c__type_description__TypeDescription * description); +// +// private: +// RCLCPP_PUBLIC +// DynamicMessageType(); +// }; } // namespace dynamic_typesupport diff --git a/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message_type_support.hpp b/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message_type_support.hpp index 149ad81bb7..8fc96744b7 100644 --- a/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message_type_support.hpp +++ b/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message_type_support.hpp @@ -64,7 +64,7 @@ class DynamicMessageTypeSupport : public std::enable_shared_from_this @@ -455,18 +456,16 @@ DynamicData::print() const bool -DynamicData::serialize(std::shared_ptr buffer) +DynamicData::serialize(rcl_serialized_message_t * buffer) { - return rosidl_dynamic_typesupport_dynamic_data_serialize( - get_rosidl_dynamic_data(), buffer.get()); + return rosidl_dynamic_typesupport_dynamic_data_serialize(get_rosidl_dynamic_data(), buffer); } bool -DynamicData::deserialize(std::shared_ptr buffer) +DynamicData::deserialize(rcl_serialized_message_t * buffer) { - return rosidl_dynamic_typesupport_dynamic_data_deserialize( - get_rosidl_dynamic_data(), buffer.get()); + return rosidl_dynamic_typesupport_dynamic_data_deserialize(get_rosidl_dynamic_data(), buffer); } diff --git a/rclcpp/src/rclcpp/dynamic_typesupport/dynamic_message.cpp b/rclcpp/src/rclcpp/dynamic_typesupport/dynamic_message.cpp deleted file mode 100644 index 550517a852..0000000000 --- a/rclcpp/src/rclcpp/dynamic_typesupport/dynamic_message.cpp +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2023 Open Source Robotics Foundation, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include -#include - -#include "rclcpp/dynamic_typesupport/dynamic_message.hpp" - -#include "rclcpp/dynamic_typesupport/dynamic_data.hpp" -#include "rclcpp/dynamic_typesupport/dynamic_serialization_support.hpp" -#include "rclcpp/dynamic_typesupport/dynamic_type.hpp" -#include "rclcpp/dynamic_typesupport/dynamic_type_builder.hpp" -#include "rclcpp/exceptions.hpp" -#include "rcutils/logging_macros.h" - -#include -#include -#include - -using rclcpp::dynamic_typesupport::DynamicMessage; -using rclcpp::dynamic_typesupport::DynamicSerializationSupport; -using rclcpp::dynamic_typesupport::DynamicType; -using rclcpp::dynamic_typesupport::DynamicTypeBuilder; - - -// CONSTRUCTION ================================================================================== -DynamicMessage::DynamicMessage(const DynamicTypeBuilder::SharedPtr dynamic_type_builder) -: DynamicData(dynamic_type_builder) {} - - -DynamicMessage::DynamicMessage(const DynamicType::SharedPtr dynamic_type) -: DynamicData(dynamic_type) {} - - -DynamicMessage::DynamicMessage( - DynamicSerializationSupport::SharedPtr serialization_support, - rosidl_dynamic_typesupport_dynamic_data_t * rosidl_dynamic_data) -: DynamicData(serialization_support, rosidl_dynamic_data) {} - - -DynamicMessage::DynamicMessage( - DynamicSerializationSupport::SharedPtr serialization_support, - std::shared_ptr rosidl_dynamic_data) -: DynamicData(serialization_support, rosidl_dynamic_data) {} - - -DynamicMessage::DynamicMessage( - DynamicData::SharedPtr parent_data, - rosidl_dynamic_typesupport_dynamic_data_t * rosidl_loaned_data) -: DynamicData(parent_data, rosidl_loaned_data) {} diff --git a/rclcpp/src/rclcpp/dynamic_typesupport/dynamic_message_type.cpp b/rclcpp/src/rclcpp/dynamic_typesupport/dynamic_message_type.cpp deleted file mode 100644 index 3f6858fea5..0000000000 --- a/rclcpp/src/rclcpp/dynamic_typesupport/dynamic_message_type.cpp +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2023 Open Source Robotics Foundation, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include -#include - -#include "rclcpp/dynamic_typesupport/dynamic_message_type.hpp" - -#include "rclcpp/dynamic_typesupport/dynamic_data.hpp" -#include "rclcpp/dynamic_typesupport/dynamic_serialization_support.hpp" -#include "rclcpp/dynamic_typesupport/dynamic_type.hpp" -#include "rclcpp/dynamic_typesupport/dynamic_type_builder.hpp" -#include "rclcpp/exceptions.hpp" -#include "rcutils/logging_macros.h" - -#include -#include -#include - -using rclcpp::dynamic_typesupport::DynamicMessageType; -using rclcpp::dynamic_typesupport::DynamicSerializationSupport; -using rclcpp::dynamic_typesupport::DynamicType; -using rclcpp::dynamic_typesupport::DynamicTypeBuilder; - - -// CONSTRUCTION ==================================================================================== -DynamicMessageType::DynamicMessageType(DynamicTypeBuilder::SharedPtr dynamic_type_builder) -: DynamicType(dynamic_type_builder) {} - - -DynamicMessageType::DynamicMessageType( - DynamicSerializationSupport::SharedPtr serialization_support, - rosidl_dynamic_typesupport_dynamic_type_t * rosidl_dynamic_type) -: DynamicType(serialization_support, rosidl_dynamic_type) {} - - -DynamicMessageType::DynamicMessageType( - DynamicSerializationSupport::SharedPtr serialization_support, - std::shared_ptr rosidl_dynamic_type) -: DynamicType(serialization_support, rosidl_dynamic_type) {} - - -DynamicMessageType::DynamicMessageType( - DynamicSerializationSupport::SharedPtr serialization_support, - const rosidl_runtime_c__type_description__TypeDescription * description) -: DynamicType(serialization_support, description) {} diff --git a/rclcpp/src/rclcpp/dynamic_typesupport/dynamic_serialization_support.cpp b/rclcpp/src/rclcpp/dynamic_typesupport/dynamic_serialization_support.cpp index 4c7d90ebde..f5d61960f1 100644 --- a/rclcpp/src/rclcpp/dynamic_typesupport/dynamic_serialization_support.cpp +++ b/rclcpp/src/rclcpp/dynamic_typesupport/dynamic_serialization_support.cpp @@ -46,8 +46,7 @@ DynamicSerializationSupport::DynamicSerializationSupport( rosidl_serialization_support, // Custom deleter [](rosidl_dynamic_typesupport_serialization_support_t * rosidl_serialization_support) -> void { - rosidl_dynamic_typesupport_serialization_support_fini(rosidl_serialization_support); - free(rosidl_serialization_support); + rosidl_dynamic_typesupport_serialization_support_destroy(rosidl_serialization_support); }); } @@ -64,8 +63,7 @@ DynamicSerializationSupport::DynamicSerializationSupport( rosidl_serialization_support_.reset( rosidl_serialization_support, [](rosidl_dynamic_typesupport_serialization_support_t * rosidl_serialization_support) -> void { - rosidl_dynamic_typesupport_serialization_support_fini(rosidl_serialization_support); - free(rosidl_serialization_support); + rosidl_dynamic_typesupport_serialization_support_destroy(rosidl_serialization_support); }); } From 9c1371d2c5328b830ce2d9380b2b1d5515bf2b84 Mon Sep 17 00:00:00 2001 From: methylDragon Date: Tue, 21 Mar 2023 16:04:30 -0700 Subject: [PATCH 4/5] Delete redundant wrapper class definitions Signed-off-by: methylDragon --- .../dynamic_typesupport/dynamic_message.hpp | 67 ++----------------- .../dynamic_message_type.hpp | 55 +-------------- 2 files changed, 7 insertions(+), 115 deletions(-) diff --git a/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message.hpp b/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message.hpp index 215a303ccb..26b6068413 100644 --- a/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message.hpp +++ b/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message.hpp @@ -34,70 +34,11 @@ namespace rclcpp namespace dynamic_typesupport { -using DynamicMessageType = DynamicType; -/// Thin wrapper around DynamicData object for message pubsub -/** - * This class: - * - Manages the lifetime of the raw pointer. - * - Exposes getter methods to get the raw pointer and shared pointers - * - Exposes the underlying serialization support API - * - * Ownership: - * - This class borrows the rosidl_dynamic_typesupport_serialization_support_t stored in the passed - * DynamicSerializationSupport. So it cannot outlive the DynamicSerializationSupport. - * - The DynamicSerializationSupport's rosidl_dynamic_typesupport_serialization_support_t pointer - * must point to the same location in memory as the stored raw pointer! - */ -// class DynamicMessage final : public DynamicData -// { -// public: -// RCLCPP_SMART_PTR_ALIASES_ONLY(DynamicMessage) -// -// // CONSTRUCTION ================================================================================== -// // Most constructors require a passed in DynamicSerializationSupport::SharedPtr, to extend the -// // lifetime of the serialization support (if the constructor cannot otherwise get it from args). -// // -// // In cases where a dynamic data pointer is passed, the serialization support composed by -// // the data should be the exact same object managed by the DynamicSerializationSupport, -// // otherwise the lifetime management will not work properly. -// -// /// Construct a new DynamicMessage with the provided dynamic type builder -// RCLCPP_PUBLIC -// explicit DynamicMessage(DynamicTypeBuilder::SharedPtr dynamic_type_builder); -// -// /// Construct a new DynamicMessage with the provided dynamic type -// RCLCPP_PUBLIC -// explicit DynamicMessage(DynamicType::SharedPtr dynamic_type); -// -// /// Assume ownership of raw pointer -// RCLCPP_PUBLIC -// DynamicMessage( -// DynamicSerializationSupport::SharedPtr serialization_support, -// rosidl_dynamic_typesupport_dynamic_data_t * rosidl_dynamic_data); -// -// /// Copy shared pointer -// RCLCPP_PUBLIC -// DynamicMessage( -// DynamicSerializationSupport::SharedPtr serialization_support, -// std::shared_ptr rosidl_dynamic_data); -// -// /// Loaning constructor -// /// Must only be called with raw ptr obtained from loaning! -// // NOTE(methylDragon): I'd put this in protected, but I need this exposed to -// // enable_shared_from_this... -// RCLCPP_PUBLIC -// DynamicMessage( -// DynamicData::SharedPtr parent_data, -// rosidl_dynamic_typesupport_dynamic_data_t * rosidl_loaned_data); -// -// // NOTE(methylDragon): Deliberately no constructor from description to nudge users towards using -// // construction from dynamic type/builder, which is more efficient -// -// private: -// RCLCPP_PUBLIC -// DynamicMessage(); -// }; +// NOTE(methylDragon): We just alias the type in this case... +// I'd have made a wrapper class but then I'd need to redirect every single +// method (or dynamic cast everywhere else), so.. no thanks. +using DynamicMessageType = DynamicType; } // namespace dynamic_typesupport diff --git a/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message_type.hpp b/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message_type.hpp index 886a406864..59115f7e45 100644 --- a/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message_type.hpp +++ b/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message_type.hpp @@ -33,59 +33,10 @@ namespace dynamic_typesupport { +// NOTE(methylDragon): We just alias the type in this case... +// I'd have made a wrapper class but then I'd need to redirect every single +// method (or dynamic cast everywhere else), so.. no thanks. using DynamicMessage = DynamicData; -/// Thin wrapper around DynamicType object for message pubsub type representation -/** - * This class: - * - Manages the lifetime of the raw pointer. - * - Exposes getter methods to get the raw pointer and shared pointers - * - Exposes the underlying serialization support API - * - * Ownership: - * - This class borrows the rosidl_dynamic_typesupport_serialization_support_t stored in the passed - * DynamicSerializationSupport. So it cannot outlive the DynamicSerializationSupport. - * - The DynamicSerializationSupport's rosidl_dynamic_typesupport_serialization_support_t pointer - * must point to the same location in memory as the stored raw pointer! - */ -// class DynamicMessageType final : public DynamicType -// { -// public: -// RCLCPP_SMART_PTR_ALIASES_ONLY(DynamicMessageType) -// -// // CONSTRUCTION ================================================================================== -// // Most constructors require a passed in DynamicSerializationSupport::SharedPtr, to extend the -// // lifetime of the serialization support (if the constructor cannot otherwise get it from args). -// // -// // In cases where a dynamic type pointer is passed, the serialization support composed by -// // the type should be the exact same object managed by the DynamicSerializationSupport, -// // otherwise the lifetime management will not work properly. -// -// /// Construct a new DynamicType with the provided dynamic type builder -// RCLCPP_PUBLIC -// explicit DynamicMessageType(DynamicTypeBuilder::SharedPtr dynamic_type_builder); -// -// /// Assume ownership of raw pointer -// RCLCPP_PUBLIC -// DynamicMessageType( -// DynamicSerializationSupport::SharedPtr serialization_support, -// rosidl_dynamic_typesupport_dynamic_type_t * rosidl_dynamic_type); -// -// /// Copy shared pointer -// RCLCPP_PUBLIC -// DynamicMessageType( -// DynamicSerializationSupport::SharedPtr serialization_support, -// std::shared_ptr rosidl_dynamic_type); -// -// /// From description -// RCLCPP_PUBLIC -// DynamicMessageType( -// DynamicSerializationSupport::SharedPtr serialization_support, -// const rosidl_runtime_c__type_description__TypeDescription * description); -// -// private: -// RCLCPP_PUBLIC -// DynamicMessageType(); -// }; } // namespace dynamic_typesupport From d4b03f9b7f6bd7821397c74e7a83e482b0629da9 Mon Sep 17 00:00:00 2001 From: methylDragon Date: Wed, 22 Mar 2023 16:43:52 -0700 Subject: [PATCH 5/5] Take ownership of description, add print, and update ser support API Signed-off-by: methylDragon --- .../dynamic_typesupport/dynamic_message.hpp | 3 +- .../dynamic_message_type.hpp | 2 +- .../dynamic_message_type_support.hpp | 8 +++- .../dynamic_serialization_support.hpp | 2 +- .../dynamic_type_builder.hpp | 24 ++++++++++ .../dynamic_message_type_support.cpp | 41 ++++++++--------- .../dynamic_type_builder.cpp | 44 +++++++++++++++++++ 7 files changed, 97 insertions(+), 27 deletions(-) diff --git a/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message.hpp b/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message.hpp index 26b6068413..9fe612141e 100644 --- a/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message.hpp +++ b/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message.hpp @@ -38,8 +38,7 @@ namespace dynamic_typesupport // NOTE(methylDragon): We just alias the type in this case... // I'd have made a wrapper class but then I'd need to redirect every single // method (or dynamic cast everywhere else), so.. no thanks. -using DynamicMessageType = DynamicType; - +using DynamicMessage = DynamicData; } // namespace dynamic_typesupport } // namespace rclcpp diff --git a/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message_type.hpp b/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message_type.hpp index 59115f7e45..3520179a56 100644 --- a/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message_type.hpp +++ b/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message_type.hpp @@ -36,7 +36,7 @@ namespace dynamic_typesupport // NOTE(methylDragon): We just alias the type in this case... // I'd have made a wrapper class but then I'd need to redirect every single // method (or dynamic cast everywhere else), so.. no thanks. -using DynamicMessage = DynamicData; +using DynamicMessageType = DynamicType; } // namespace dynamic_typesupport diff --git a/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message_type_support.hpp b/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message_type_support.hpp index 8fc96744b7..596dead05f 100644 --- a/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message_type_support.hpp +++ b/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_message_type_support.hpp @@ -145,6 +145,12 @@ class DynamicMessageTypeSupport : public std::enable_shared_from_this serialization_support); /// Move constructor diff --git a/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_type_builder.hpp b/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_type_builder.hpp index 5e3dbaeb0f..60cd03968f 100644 --- a/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_type_builder.hpp +++ b/rclcpp/include/rclcpp/dynamic_typesupport/dynamic_type_builder.hpp @@ -282,6 +282,30 @@ class DynamicTypeBuilder : public std::enable_shared_from_this #include +#include "rosidl_runtime_c/type_description_utils.h" #include #include @@ -225,7 +226,7 @@ DynamicMessageTypeSupport::init_rosidl_message_type_support_( DynamicSerializationSupport::SharedPtr serialization_support, DynamicMessageType::SharedPtr dynamic_message_type, DynamicMessage::SharedPtr dynamic_message, - const rosidl_runtime_c__type_description__TypeDescription * description) + rosidl_runtime_c__type_description__TypeDescription * description) { bool middleware_supports_type_discovery = rmw_feature_supported(RMW_MIDDLEWARE_SUPPORTS_TYPE_DISCOVERY); @@ -242,8 +243,11 @@ DynamicMessageTypeSupport::init_rosidl_message_type_support_( } // NOTE(methylDragon): We don't finalize the rosidl_message_type_support->data since its members - // are they're managed by the passed in SharedPtr wrapper classes - rosidl_message_type_support_ = std::make_shared(); + // are managed by the passed in SharedPtr wrapper classes + rosidl_message_type_support_.reset( + new rosidl_message_type_support_t(), + [](rosidl_message_type_support_t * ts) -> void {free(const_cast(ts->data));} + ); if (!rosidl_message_type_support_) { RCUTILS_LOG_ERROR_NAMED( @@ -270,26 +274,8 @@ DynamicMessageTypeSupport::init_rosidl_message_type_support_( ts_impl->serialization_support = serialization_support->get_rosidl_serialization_support(); ts_impl->dynamic_type = dynamic_message_type->get_rosidl_dynamic_type(); ts_impl->dynamic_data = dynamic_message->get_rosidl_dynamic_data(); + ts_impl->description = description; rosidl_message_type_support_->func = get_message_typesupport_handle_function; - - if (description) { - ts_impl->description = rosidl_runtime_c__type_description__TypeDescription__create(); - if (ts_impl->description == NULL) { - RCUTILS_LOG_ERROR_NAMED( - rmw_dynamic_typesupport_c__identifier, - "Could not create type description to assign into"); - rosidl_message_type_support_.reset(); - } - - if (!rosidl_runtime_c__type_description__TypeDescription__copy( - description, ts_impl->description)) - { - RCUTILS_LOG_ERROR_NAMED( - rmw_dynamic_typesupport_c__identifier, - "Could not copy type description"); - rosidl_message_type_support_.reset(); - } - } } @@ -397,3 +383,14 @@ DynamicMessageTypeSupport::get_shared_dynamic_message() const { return dynamic_message_; } + + +// METHODS ========================================================================================= +void +DynamicMessageTypeSupport::print_description() const +{ + if (!description_) { + RCUTILS_LOG_ERROR("Can't print description, no bound description!"); + } + rosidl_runtime_c_type_description_utils_print_type_description(description_.get()); +} diff --git a/rclcpp/src/rclcpp/dynamic_typesupport/dynamic_type_builder.cpp b/rclcpp/src/rclcpp/dynamic_typesupport/dynamic_type_builder.cpp index 5cec3d7904..6f205ffe2b 100644 --- a/rclcpp/src/rclcpp/dynamic_typesupport/dynamic_type_builder.cpp +++ b/rclcpp/src/rclcpp/dynamic_typesupport/dynamic_type_builder.cpp @@ -490,3 +490,47 @@ DynamicTypeBuilder::add_complex_bounded_sequence_member( get_rosidl_dynamic_type_builder(), id, name.c_str(), name.size(), nested_type.get_rosidl_dynamic_type(), sequence_bound); } + + +void +DynamicTypeBuilder::add_complex_member_builder( + rosidl_dynamic_typesupport_member_id_t id, const std::string & name, + DynamicTypeBuilder & nested_type_builder) +{ + rosidl_dynamic_typesupport_dynamic_type_builder_add_complex_member_builder( + get_rosidl_dynamic_type_builder(), id, name.c_str(), name.size(), + nested_type_builder.get_rosidl_dynamic_type_builder()); +} + + +void +DynamicTypeBuilder::add_complex_array_member_builder( + rosidl_dynamic_typesupport_member_id_t id, const std::string & name, + DynamicTypeBuilder & nested_type_builder, size_t array_length) +{ + rosidl_dynamic_typesupport_dynamic_type_builder_add_complex_array_member_builder( + get_rosidl_dynamic_type_builder(), id, name.c_str(), name.size(), + nested_type_builder.get_rosidl_dynamic_type_builder(), array_length); +} + + +void +DynamicTypeBuilder::add_complex_unbounded_sequence_member_builder( + rosidl_dynamic_typesupport_member_id_t id, const std::string & name, + DynamicTypeBuilder & nested_type_builder) +{ + rosidl_dynamic_typesupport_dynamic_type_builder_add_complex_unbounded_sequence_member_builder( + get_rosidl_dynamic_type_builder(), id, name.c_str(), name.size(), + nested_type_builder.get_rosidl_dynamic_type_builder()); +} + + +void +DynamicTypeBuilder::add_complex_bounded_sequence_member_builder( + rosidl_dynamic_typesupport_member_id_t id, const std::string & name, + DynamicTypeBuilder & nested_type_builder, size_t sequence_bound) +{ + rosidl_dynamic_typesupport_dynamic_type_builder_add_complex_bounded_sequence_member_builder( + get_rosidl_dynamic_type_builder(), id, name.c_str(), name.size(), + nested_type_builder.get_rosidl_dynamic_type_builder(), sequence_bound); +}