Random thought: #[repr(C++)]?


Hi, while we can mimic a struct defined in C header with #[repr©] for use of FFI, i wonder if it is possible to mimic the struct/class layout defined in a C++ header with something like #[repr(C++)]? It can calculate the proper offsets of the fields, taking C++ inheritance into account…

I think it can greatly ease the inter-op of Rust/C++, since we’ll be able to access the data directly…

I know it sounds a bit overkill, but i’d really like to see a library accomplish this with some minimal support from the language side… Then we’ll be able to provide more support for C++ headers.


Forgive my ignorance, but how #including a templated struct/class work in rust? What does that mean in terms of rust? In C++ templates aren’t checked until instantiation, would the rust compiler be doing this?


My understanding was that neither C nor C++ has a formally standardized ABI, and only C happens to have a universal de facto ABI that repr© can claim to mimic accurately (and the recent chatter on https://github.com/rust-lang/rfcs/issues/1982 shows even that isn’t as clear-cut as we’d like). In other words, afaik a “repr(C++)” feature is impossible in a very fundamental sense even if we ignore all the issues presented by C++ templates. I’ve heard a lot of C++ implementations use the “Itanium ABI”, but it kinda needs to be all of them for this feature to work.

Finding ways to improve C++ interop is definitely important though. I wish I had some concrete ideas on how it could be done.


It shouldn’t be quite that bad. This is only my personal understanding as well, but the situation at present should be that there is only one de facto C++ ABI per config.guess tuple, and that ABI will either be based on the “Itanium ABI” or it will be the Visual Studio ABI. Conveniently, LLVM already supports both. :slight_smile:

Having said that, I suspect this is still a big can of worms, and it would be wise to scope it down a bit before even starting. What types of interop between a Rust caller and a C++ callee would actually be useful? How about the other way around?


Doesn’t the pack pragma complicate this a bit, or am I misunderstanding the situation?


…admittedly the utility of ffi with code that uses pack in a weird way is…questionable.


It does. I confess I tend to think pragma pack is simultaneously too large and too feeble a hammer for nearly all situations, so I don’t much care whether it works. :shrug:

(But wouldn’t we just have to pass the pragma setting down to LLVM and let it do its thing?)


In the areas where C and C++ types intersect, #[repr(C)] should be fine for C++ interop. In the areas where C++ goes beyond C, especially templates and inheritance, I don’t think you can even express those types in Rust at all, let alone apply a #[repr(C++)] to it.

Or to reverse the question, what Rust types are you writing that can’t be #[repr(C)] but could hypothetically use a #[repr(C++)]?