Open rodrigorc opened 1 week ago
After some extra investigation, it looks like MSVC has two kinds of return structs: small and big.
The "small" return ABI is used for C structs that have 8 bytes or fewer, and the value is returned in registries.
The "big" return ABI is used for structs greater than 8 bytes or those with C++ parts (constructors, destructors, vtables, base members...).
I think that the relevant code in CLang would be:
The issue here is that in Rust there is no way to choose which one you want. When you write #[repr(C)]
into a struct it will use the small or big ABI depending on the size of the type, not caring about the C++ pieces.
So a C++ struct with sizeof <= 8 and a constructor cannot be expressed as a FFI-to-MSVC type in current Rust.
I'm not sure what Bindgen should do here. The easiest solution would be just not to emit bindings for such a function. I've tried looking at the code, but came back empty handed...
I am happily using bindgen to link Rust to a C++ library, and it works great... except when compiling for the MSVC target (that is
i686-pc-windows-msvc
orx86_64-pc-windows-msvc
), that my program crashes badly with random exceptions.I have reduced the faulty code to the code in this sample repo, ready to run:
https://github.com/rodrigorc/testabi
Input C/C++ Header
There are two types, for reference,
Ok
works fine,Err
fails. The only difference is the constructor, that IIUIC makes the type non-POD and changes the ABI.Bindgen Invocation
It fails both with
clang
andmsvc
compilers.Actual Results
When running the program in windows, natively compiled, it prints garbage:
Or crashes with something like:
Or sometimes other less known exceptions. I reckon the stack is getting corrupted.
Expected Results
When cross compiling from Linux, or running natively on Linux, it prints the expected: