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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions