Skip to content

Different types on Windows? #1361

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
NoraCodes opened this issue Aug 9, 2018 · 4 comments
Closed

Different types on Windows? #1361

NoraCodes opened this issue Aug 9, 2018 · 4 comments

Comments

@NoraCodes
Copy link

Input C/C++ Header

// We have a lot of enums defined using this macro
#define __UI_ENUM(s) typedef unsigned int s; enum

// Like this
_UI_ENUM(uiAlign) {
    uiAlignFill,
    uiAlignStart,
    uiAlignFill,
    uiAlignEnd,
}

Bindgen Invocation

// Generate libui bindings on the fly
    let bindings = BindgenBuilder::default()
        .header("wrapper.h")
        .opaque_type("max_align_t") // For some reason this ends up too large
        .generate()
        .expect("Unable to generate bindings");

The Issue

I use these enums in Rust code, for instance, here:

// Where GridAlignment is an enum and ui_sys is the bindings
use ui_sys::{self, uiAlign};
impl GridAlignment {
    fn into_ui_align(self) -> uiAlign {
        use self::GridAlignment::*;
        match self {
            Fill => ui_sys::uiAlignFill,
            Start => ui_sys::uiAlignStart,
            Center => ui_sys::uiAlignCenter,
            End => ui_sys::uiAlignEnd
        }
    }
}

On Linux, this code works. On Windows, it does not:

error[E0308]: match arms have incompatible types
   --> iui\src\controls\layout.rs:283:9
    |
283 | /         match self {
284 | |             Fill => ui_sys::uiAlignFill,
    | |                     ------------------- match arm with an incompatible type
285 | |             Start => ui_sys::uiAlignStart,
286 | |             Center => ui_sys::uiAlignCenter,
287 | |             End => ui_sys::uiAlignEnd 
288 | |         }
    | |_________^ expected u32, found i32

Check out more details, if needed, at LeoTindall/libui-rs#29

@emilio
Copy link
Contributor

emilio commented Aug 9, 2018

This is invalid, I think. MSVC generates a different underlying type for enums by default, see:

https://godbolt.org/g/i9EMTL

That program, which for reference is:

#include <type_traits>

#define __UI_ENUM(s) typedef unsigned int s; enum
extern "C" {
__UI_ENUM(uiAlign) {
    uiAlignFill,
    uiAlignStart,
    uiAlignEnd,
};
}

int main() {
  static_assert(
    std::is_same<std::underlying_type<decltype(uiAlignFill)>::type, unsigned>::value,
    "Huh");
}

Only fails to compile on MSVC.

So bindgen is right in this case, even if it ends up not quite mattering given the values never go out of range (I hope :)).

If it was C++ you could use enum class or something to force the type layout you want... You could also explicitly cast in the rust side where it matters, or use rustified_enum("ui.*"), for example, if you're generating bindings on the fly and you know that you never generate values that are not specified in a given enum variant on the rust side.

Let me know if I can help more to get the bindings working and in a sane state, binding to libui is really cool!

@emilio emilio closed this as completed Aug 9, 2018
@NoraCodes
Copy link
Author

Thanks for reproducing that! MSVC is... wrong in this case, I think? We do explicitly ask for an unsigned enum.

In any case, using Rust-ified enums should be fine here. I'll let you know if I have any more issues.

@davidkna
Copy link

davidkna commented Aug 9, 2018

I don't think so because I think the enum is anonymous and uiAlign is only an alias for unsigned here and enums are not guranteed to be unsigned AFAIK.

@NoraCodes
Copy link
Author

Oh, I see! Thanks, I misunderstood what that declaration was doing.

bminortx added a commit to Tangram-Vision/realsense-rust that referenced this issue Mar 17, 2021
It appears as if bindgen chooses i32 always for Windows, but varies for Mac and
Linux. Relevant links:

- https://users.rust-lang.org/t/bindgen-and-enum-types/34370
- rust-lang/rust-bindgen#1361

However, this behavior isn't in line with the C standard, which states:

> The identifiers in an enumerator list are declared as constants that have type
int and may appear wherever such are permitted.

To remedy this for all platforms, enums are now default type i32.
bminortx added a commit to Tangram-Vision/realsense-rust that referenced this issue Mar 17, 2021
It appears as if bindgen chooses i32 always for Windows, but varies for Mac and
Linux. Relevant links:

- https://users.rust-lang.org/t/bindgen-and-enum-types/34370
- rust-lang/rust-bindgen#1361

However, this behavior isn't in line with the C standard, which states:

"The identifiers in an enumerator list are declared as constants that have type
int and may appear wherever such are permitted."

To remedy this for all platforms, enums are now default type i32.
ConnorGray added a commit to WolframResearch/wolfram-library-link-rs that referenced this issue Jun 11, 2022
…ants

This is a fix for:

    #29

The existing code assumed that the Wolfram LibraryLink constants would have
the same size and signedness on all platforms. This assumption was not correct
on Windows targeting MSVC, where constants that would be u32 on other platforms
would be i32.

See also:

    * rust-lang/rust-bindgen#1244
    * rust-lang/rust-bindgen#1361
ConnorGray added a commit to WolframResearch/wolfram-library-link-rs that referenced this issue Jun 11, 2022
…ants (#41)

This is a fix for:

    #29

The existing code assumed that the Wolfram LibraryLink constants would have
the same size and signedness on all platforms. This assumption was not correct
on Windows targeting MSVC, where constants that would be u32 on other platforms
would be i32.

See also:

    * rust-lang/rust-bindgen#1244
    * rust-lang/rust-bindgen#1361
ConnorGray added a commit to WolframResearch/wstp-rs that referenced this issue Jun 12, 2023
On Windows, anonymous enums are translated to i32.
On Linux and macOS, they're translated to u32.

This fixes: #51

See also: rust-lang/rust-bindgen#1361
ConnorGray added a commit to WolframResearch/wstp-rs that referenced this issue Jun 12, 2023
On Windows, anonymous enums are translated to i32.
On Linux and macOS, they're translated to u32.

This fixes: #51

See also: rust-lang/rust-bindgen#1361
sgoll added a commit to HMIProject/open62541 that referenced this issue Dec 18, 2023
The reason for this is that MSVC uses signed enum types by default.

Cf. rust-lang/rust-bindgen#1361 (comment)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants