Skip to content

Commit

Permalink
Merge pull request #428 from dora-rs/c++-ros2-constants
Browse files Browse the repository at this point in the history
Expose ROS2 constants in generated bindings (Rust and C++)
  • Loading branch information
phil-opp authored Feb 29, 2024
2 parents c75d2a7 + 4175936 commit ac6eaec
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 12 deletions.
16 changes: 8 additions & 8 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions apis/c++/node/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -242,3 +242,15 @@ else
}
```
### Constants
Some ROS2 message definitions define constants, e.g. to specify the values of an enum-like integer field.
The Dora ROS2 bridge exposes these constants in the generated bindings as functions.
For example, the `STATUS_NO_FIX` constant of the [`NavSatStatus` message](https://docs.ros.org/en/jade/api/sensor_msgs/html/msg/NavSatStatus.html) can be accessed as follows:
```c++
assert((sensor_msgs::const_NavSatStatus_STATUS_NO_FIX() == -1));
```

(Note: Exposing them as C++ constants is not possible because it's [not supported by `cxx` yet](https://github.com/dtolnay/cxx/issues/1051).)
3 changes: 3 additions & 0 deletions examples/c++-ros2-dataflow/node-rust-api/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ int main()
}
}

// try to access a constant for testing
assert((sensor_msgs::const_NavSatStatus_STATUS_NO_FIX() == -1));

std::cout << "GOODBYE FROM C++ node (using Rust API)" << std::endl;

return 0;
Expand Down
52 changes: 48 additions & 4 deletions libraries/extensions/ros2-bridge/msg-gen/src/types/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,27 @@ 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: &str, package_name: &str) -> impl ToTokens {
let name = format_ident!("const_{package_name}__{struct_name}_{}", self.name);
let cxx_name = format_ident!("const_{struct_name}_{}", self.name);
let type_ = self.r#type.type_tokens();
quote! {
#[namespace = #package_name]
#[cxx_name = #cxx_name]
pub fn #name () -> #type_;
}
}

fn cxx_method_impl_token_stream(&self, struct_raw_name: &Ident) -> impl ToTokens {
let const_name = format_ident!("{}", self.name);
let name = format_ident!("const_{struct_raw_name}_{}", self.name);
let type_ = self.r#type.type_tokens();
quote! {
#[allow(non_snake_case, dead_code)]
fn #name () -> #type_ { ffi::#struct_raw_name::#const_name }
}
}
}

/// A message definition
Expand All @@ -133,15 +154,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(&self.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() {
Expand All @@ -154,8 +189,15 @@ impl Message {
pub struct #struct_raw_name {
#(#rust_type_def_inner)*
}

#cxx_consts
};
let impls = quote! {
impl ffi::#struct_raw_name {
#(#constants_def_inner)*

}

impl crate::_core::InternalDefault for ffi::#struct_raw_name {
fn _default() -> Self {
Self {
Expand All @@ -170,6 +212,8 @@ impl Message {
crate::_core::InternalDefault::_default()
}
}

#(#cxx_const_impl_inner)*
};

(def, impls)
Expand Down

0 comments on commit ac6eaec

Please sign in to comment.