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.

3 Likes

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++)]?

4 Likes

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.