Reputation: 163
I am designing a communication middleware for use in an application which has a module in Ada and many modules in C++ which communicates passing parameters (scalar values) and structures. The application runs in MS Windows XP and Windows 7, the C++ part is being developed in MSVC++ 2008, the Ada part is being developed using GPS/GNAT. Ada version is 1995 but we're in the middle of a compiler migration (newer version of GPS/GNAT) with the possibility of using newer Ada spec.
The middleware is being written in C++ and I would like to use a union type containing all types that are passed between modules so I won't need to specify one put/get function for each type that is used on the system.
The question is, are C++ unions binary compatible to Ada variant records? In other words, if I pass a C++ union to Ada code will it be able to read it as a Variant record? (and vice-versa)
I think that for this to be possible some adjustments will be necessary... (Eg.: C++ unions do not contain a member which describes its content while Ada variant records do)
Upvotes: 6
Views: 2002
Reputation:
Yes.
Ada is compatible with C/C++ Unions. See here for how to do it (pdf) In particular Page 5 shows how to do it with Unions & Tags. It should be the same for using Discriminant records. (Caveat: it is probably not the compiler you are using, but i would be very surprised if yours didnt behave the same way!)
Upvotes: 5
Reputation: 44824
As MSalters mentioned, it won't work unless the C union for some reason contains a field designating the variant. As this isn't required in C, it won't often work. However, since you control the implemeation of that C type, you can make it work. Just be sure to have a field right before the union that designates which union is being used.
To make it fully binary-compatible with your C union-bearing struct, you will probably need to go with a simple Ada record type, along with a record representation clause to make sure the fields are laid out in the same places your C compiler happens to put them. And yes, that does leave you vulnerable to C compiler changes causing layout changes. You can try to protect against that with bitfields in your C code, but they aren't powerful enough to really lay things out the way Ada record rep clauses can. That's one of the reasons we prefer to use Ada for low-level work.
I should mention that, when last I checked, the Windows version of Gnat was not linker-compatible with VisualStudio binaries. The only way I know of to get those two compilers to work together is to put the entire interface in a DLL. Otherwise, you will probably either need to use GCC to build your C++ system, or use some other Ada compiler, like ObjectAda.
Upvotes: 3
Reputation: 8522
Possibly.
Ada 2005 provides the Unchecked_Union pragma which allows a program to "[specify] an interface correspondence between a given discriminated type and some C union. The pragma specifies that the associated type shall be given a representation that leaves no space for its discriminant(s)."
From my reading of the RM section, one declares an Ada type with the discriminant(s) needed to define a variant record, but no storage space is allocated for the discriminant(s). I take it this means on the Ada side that the discriminant cannot subsequently be referenced. (There are other restrictions as well, like all the fields must be C-compatible, see RM B.3.3 for more info.)
I've never used this pragma, and I can't help but think that it will require some experimentation to get it to (hopefully) work with your system. Good luck!
Upvotes: 8
Reputation: 180303
No. As you state yourself, Ada variant records contain a tag field. The C union does not have that. (At least not in MSVC++ and GCC - it's allowed by ISO C.)
Upvotes: 2