Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upFFI and union #5492
Comments
This comment has been minimized.
This comment has been minimized.
|
There could be |
This comment has been minimized.
This comment has been minimized.
|
Referencing Aatch/rust-xcb#2. |
This comment has been minimized.
This comment has been minimized.
|
referencing servo/servo#398 referencing servo/rust-mozjs#9 |
This comment has been minimized.
This comment has been minimized.
|
The |
This comment has been minimized.
This comment has been minimized.
|
brson mentions in the description for #6346 that a "macro based solution" would be appropriate here, though I do not current know what that would entail. (It sounds to me like a potential alternative to the changes to the grammar to add |
This comment has been minimized.
This comment has been minimized.
|
Nominating for milestone 3, feature complete. |
This comment has been minimized.
This comment has been minimized.
|
I don't think a "macro-based solution" would be appropriate, as you need to restrict the valid range of values at the site of usage, which macros cannot do. |
This comment has been minimized.
This comment has been minimized.
|
An attribute on an enum that makes it have no discriminant and makes any match on the variant-part succeed, should be sufficient. Not pretty but neither are C union semantics. |
This comment has been minimized.
This comment has been minimized.
|
accepted for feature-complete milestone |
This comment has been minimized.
This comment has been minimized.
Skrylar
commented
Dec 13, 2013
|
I ran in to this problem recently as well; Allegro makes use of Unions for passing events around in C, which turns out to be a pain to deal with in Rust. |
This comment has been minimized.
This comment has been minimized.
|
We do want to solve this problem eventually, but it need not block 1.0. Assigning P-low. |
pnkfelix
added
P-low
and removed
P-high-untriaged
labels
Feb 13, 2014
This comment has been minimized.
This comment has been minimized.
alxkolm
commented
Nov 3, 2014
|
What status? |
This comment has been minimized.
This comment has been minimized.
alexchandel
commented
Jan 21, 2015
|
What's the recommended way to do FFI-compatible unions? |
This comment has been minimized.
This comment has been minimized.
|
I believe structs containing a field which is at least as big as the largest type the union can represent and manual transmutes is the state of the art right now. |
This comment has been minimized.
This comment has been minimized.
Make sure you get the alignments right. The struct should have |
This comment has been minimized.
This comment has been minimized.
alexchandel
commented
Jan 21, 2015
|
@jdm Even when variants are different sizes? |
This comment has been minimized.
This comment has been minimized.
|
Also, the overall size of the union is a multiple of the alignment of its most-aligned variant. This union has the size of 8: union A {
int32_t intval;
char chars[5];
};Which would require a Rust representation like: #[repr(C)]
struct A {
union_data: [i32; 2]
}So yes, representing unions is not for the unwary. |
This comment has been minimized.
This comment has been minimized.
alexchandel
commented
Jan 22, 2015
|
@mzabaluev For a C union like this: struct INPUT {
DWORD type;
union {
MOUSEINPUT mi;
KEYBDINPUT ki;
HARDWAREINPUT hi;
};
};I use a struct field rather bytes. It's easier because the size and alignment change between platforms, and you can't do #[repr(C)]
pub struct MOUSEINPUT { ... }
#[repr(C)]
pub struct KEYBDINPUT { ... }
#[repr(C)]
pub struct HARDWAREINPUT { ... }
#[repr(C)]
pub struct INPUT {
pub tag_: DWORD,
pub union_: MOUSEINPUT, // MOUSEINPUT largest and most aligned
} |
This comment has been minimized.
This comment has been minimized.
|
@alexchandel Good when it works, but sometimes the largest variant is not the most aligned, like in my example above. |
This comment has been minimized.
This comment has been minimized.
niconiconico9
commented
Jul 11, 2015
|
Is there a reason why this bug is tagged as "P-low"? |
This comment has been minimized.
This comment has been minimized.
Daggerbot
commented
Aug 24, 2015
|
I don't know how feasible it would be to implement, but an example usage could be:
Like C unions, each field would start at the beginning of the struct, and the size of the struct would be that of its longest field. This wouldn't require adding A macro based solution could look something like:
The only thing that prevented me from writing this macro is the inability to determine the size of the union at compile time. The best workaround I could come up with is providing a guess of the size of the largest field and making the union generate tests to verify this.
Of course, it would be much easier on developers of language bindings to have unions available as a language feature. |
This comment has been minimized.
This comment has been minimized.
|
|
This comment has been minimized.
This comment has been minimized.
|
I'm interested in unions as well, for several Linux kernel APIs. The proposal of having an "unsafe union", guaranteed to match the C layout, would work perfectly; almost any non-trivial instance of such a C union only makes sense to access in an unsafe block, given its trivial equivalence to the unsafe |
This comment has been minimized.
This comment has been minimized.
serprex
commented
Oct 25, 2015
|
Most unions in C have a descriptor field, therefore there's a need for 2 cases (has-desciptor & has-no-descriptor). Being able to specify a struct-unique enum with custom type descriptor & the fields corresponding values would allow Rust to use the union in a type safe manner while being able to interoperate with C APIs Essentially something like
Using unsafe struct to handle cases where the type descriptor isn't adjacent to the union. Even then, something could be done like
Then there'd need to be compile-time machinery that makes sure there's a valid u8 behind the enum in definitions, though user code would access a The issue of having typeoffset could be resolved by requiring explicit enums only be contained in structs & have enum_explicit_layout_typeoffset be specified by the struct. Would require a bit more strictness though since one wouldn't be able to know how to find the descriptor of an &IntOrFloat parameter |
This comment has been minimized.
This comment has been minimized.
|
@serprex: I don't think it's worthwhile to add language support for external descriptors of unions, even in cases where there is a 1:1 match between a single descriptor field value and a union variant. The code using unions is expected to be close to FFI, where unsafe is the norm; so variant matching can be always unsafe, and the burden of ensuring the correct variant would be completely on the programmer, as it is in C. |
This comment has been minimized.
This comment has been minimized.
|
@mzabaluev I agree. For a first pass, at least, we just need an unsafe construct to access fields of a C union in a C-compatible, interoperable way. We can always produce a safe wrapper around that, and even produce macros to generate such wrappers for common cases. |
This comment has been minimized.
This comment has been minimized.
|
I posted a preliminary proposal using |
This comment has been minimized.
This comment has been minimized.
|
Closing in favour of rust-lang/rfcs#877. |
sanxiyn commentedMar 22, 2013
How would one call C functions involving union with Rust FFI?
SpiderMonkey's jsval is one example.