Guarita
Guarita

Reputation: 163

Can an Ada Variant Record be binary compatible to a C++ union?

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

Answers (4)

user571138
user571138

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

T.E.D.
T.E.D.

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

Marc C
Marc C

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

MSalters
MSalters

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

Related Questions