Skip to content

Potential issue with message definitions with fields with type char and signedness across platforms #115

@molysgaard

Description

@molysgaard

char is a very strange C-type. In the C-spec (and C++), it does not have a defined signedness.

This leads to some challenges when one is working with code on different platforms.
As an example, the char type has different signedness on x86 and aarch64:

  • On x86, a char is a signed 8-bit integer [-128..127]
  • On aarch64, a char is an unsigned 8-bit integer [0..255]

I have some code that runs on both x86 and aarch64, and a Yocto cross-compilation system to cross-compile from our x86 build machines onto our aarch64 robot machines.

We specify our messages using OMG IDL instead of the normal ROS2 .msg or .srv files.
R2R does a great job of parsing the generated C-headers and libraries and generating correct Rust code to interface with this, but I think I might have found an inconsistency in how r2r handles the OMG IDL char type.

On my x86 machine, an OMG IDL message with a char type gets type std::ffi::c_char in the generated Rust.
From the OMG IDL spec, I understand it so that char always is an unsigned 8-bit integer in the range [0..255]. Ref: https://www.omg.org/spec/IDL/4.2/PDF Section 7.2.6.2.1

I have also checked the C-headers generated by colcon and it generates unsigned char for my OMG IDL char field.

I tried to look through the r2r_msg_gen crate and found:

    pub fn to_rust_type(&self) -> proc_macro2::TokenStream {
        match self {
            MemberType::Bool => quote! { bool },
            MemberType::I8 => quote! { i8 },
            MemberType::I16 => quote! { i16 },
            MemberType::I32 => quote! { i32 },
            MemberType::I64 => quote! { i64 },
            MemberType::U8 => quote! { u8 },
            MemberType::U16 => quote! { u16 },
            MemberType::U32 => quote! { u32 },
            MemberType::U64 => quote! { u64 },
            MemberType::U128 => quote! { u128 },
            MemberType::F32 => quote! { f32 },
            MemberType::F64 => quote! { f64 },
            MemberType::Char => quote! { std::ffi::c_char },
            MemberType::WChar => quote! { u16 },
            MemberType::String => quote! { std::string::String },
            MemberType::WString => quote! { std::string::String },
            MemberType::Message => quote! { message },
        }
    }

I realized that I do not know enough about how r2r is implemented to know if this is the only place that needs to be changed to fix this. I am not even 100% sure that r2r does something wrong. I would love it if someone with a deeper understanding of r2r could have a look at this.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions