From e7f5d47cc908250cf4fc882a3d9a4d4d422754f9 Mon Sep 17 00:00:00 2001 From: Philipp Oppermann Date: Wed, 28 Feb 2024 12:17:51 +0100 Subject: [PATCH] Expose ROS2 constants in generated bindings (Rust and C++) --- .../ros2-bridge/msg-gen/src/types/message.rs | 52 +++++++++++++++++-- 1 file changed, 48 insertions(+), 4 deletions(-) diff --git a/libraries/extensions/ros2-bridge/msg-gen/src/types/message.rs b/libraries/extensions/ros2-bridge/msg-gen/src/types/message.rs index b8d81173..8a40c8e4 100644 --- a/libraries/extensions/ros2-bridge/msg-gen/src/types/message.rs +++ b/libraries/extensions/ros2-bridge/msg-gen/src/types/message.rs @@ -107,6 +107,28 @@ impl Constant { let value = self.r#type.value_tokens(&self.value); quote! { pub const #name: #type_ = #value; } } + + fn cxx_method_def_token_stream( + &self, + struct_name: &Ident, + package_name: &str, + ) -> impl ToTokens { + let name = format_ident!("const_{struct_name}_{}", self.name); + let cxx_name = format_ident!("const_{}", self.name); + let type_ = self.r#type.type_tokens(); + quote! { + #[namespace = #package_name] + #[cxx_name = #cxx_name] + pub fn #name (self: &#struct_name) -> #type_; + } + } + + fn cxx_method_impl_token_stream(&self, struct_name: &Ident) -> impl ToTokens { + let const_name = format_ident!("{}", self.name); + let name = format_ident!("const_{struct_name}_{}", self.name); + let type_ = self.r#type.type_tokens(); + quote! { pub fn #name (self: &ffi::#struct_name) -> #type_ { Self::#const_name }} + } } /// A message definition @@ -133,15 +155,29 @@ impl Message { let rust_type_def_inner = self.members.iter().map(|m| m.rust_type_def(&self.package)); let constants_def_inner = self.constants.iter().map(|c| c.token_stream()); + let cxx_const_def_inner = self + .constants + .iter() + .map(|c| c.cxx_method_def_token_stream(&struct_raw_name, package_name)); + let cxx_const_impl_inner = self + .constants + .iter() + .map(|c| c.cxx_method_impl_token_stream(&struct_raw_name)); let rust_type_default_inner = self.members.iter().map(|m| m.default_value()); - let attributes = if gen_cxx_bridge { - quote! { + let (attributes, cxx_consts) = if gen_cxx_bridge { + let attributes = quote! { #[namespace = #package_name] #[cxx_name = #cxx_name] - } + }; + let consts = quote! { + extern "Rust" { + #(#cxx_const_def_inner)* + } + }; + (attributes, consts) } else { - quote! {} + (quote! {}, quote! {}) }; if self.members.is_empty() { @@ -154,8 +190,16 @@ impl Message { pub struct #struct_raw_name { #(#rust_type_def_inner)* } + + #cxx_consts }; let impls = quote! { + impl ffi::#struct_raw_name { + #(#constants_def_inner)* + + #(#cxx_const_impl_inner)* + } + impl crate::_core::InternalDefault for ffi::#struct_raw_name { fn _default() -> Self { Self {