From: wallace@bonmot (Richard Wallace)
Newsgroups: comp.lang.ada
Subject: Variant Records from Ada to C
Date: 2 Oct 92 19:01:49 GMT
Distribution: comp.lang.ada
Organization: Digital Equipment Corporation
X-Newsreader: Tin 1.1 PL3

In reply to Randy's post of Sharon's question we'll have to look at
several issues.

	Issues:

	1) From the given code (following) the mapping of data from
	   the Ada record xrec to the C structure xrec will *NOT WORK*.
	   The interface to the void function pass_string_array *WILL
	   NOT* work either due to the passing of a non-ASCII.NUL terminated
	   string to the C function (printf will bomb even if it makes it
	   past the call interface).
	   The reasons why the void function pass_record will not work are:
	   a) The order and types of data will not overlay properly.
	   b) pragma INTERFACE does not provide a data space mapping
	      it only maps entry points (and based on vendor, only hints to
	      calling standards).

	2) pragma INTERFACE is implementation dependent.  For VAX Ada
	   there are additional pragmas for IMPORT_PROCEDURE,
	   IMPORT_VALUED_PROCEDURE et.al.  So while the following Ada
	   is valid it is highly dependent on the implementation of the
	   Ada and C compilers for that host if the interface will map
	   at all.  We'll ignore cross-host here (that in and of itself
	   is a subject for another posting).

	3) The data storage issues between the Ada and C compiler are the
	   most germane to this posting.  Note the additional data objects
	   in the C structure xrec.  There are no corresponding objects in the
	   Ada record for things like unsigned s2_offset, dv1, dv2, etc.
	   After fixing the data object issues between the C structure and
	   Ada record (variant or not) I would STRONGLY recommend that
	   the pragma PACK be used for the Ada data structure.  While some
	   may argue that it may not be necessary here I would would rather
	   be safe than sorry.
	   Also in the C program I would take great care to be very specific
	   on the exact matching of data types to memory allocation.  The
	   pragma INTERFACE *DOES NOT* guarantee data alignment nor data
	   passing standard (r-value versus l-value, etc.).

Richard Wallace
Digital Equipment Corporation
301 Rockrimmon Blvd. South
CXO2-1/7A
Colorado Springs, CO 80919-2398
(719)548-2792
<wallace@cookie.enet.dec.com>

	"The opinions expressed are my own, Uncle Bob
	 may, or may not, agree with me."

<<<<original code>>>>

: with system;
: 
: procedure a is
:    procedure pass_string_array( str : system.address);
:    pragma interface(c, pass_string_array);
:    procedure pass_record( rec : system.address);
:    pragma interface(c, pass_record);
:    type xrec (p1 : integer; p2: integer) is
:    record
:       b  : integer;
:       s1 : string(1..p1);
:       c  : integer;
:       s2 : string(1..p2);
:       case p1 is
:          when 7 =>
:             fld1 : integer;
:          when others =>
:             fld2 : integer;
:       end case;
:    end record;
:    myrec : xrec(7,8);
: begin
:    myrec.b := 66;
:    myrec.c := 77;
:    myrec.s1 := "AAAAABB";
:    myrec.s2 := "CCCCCDDD";
:    myrec.fld1 := 88;
:    pass_string_array(myrec.s1'address);
:    pass_string_array(myrec.s2'address);
:    pass_record(myrec'address);
: end;
: 
: C file.
: 
: #include <stdio.h>
:    typedef struct xrec {      
:       int p1;
:       int p2;
:       int b;
:       unsigned s1_offset;
:       struct {
:          int element_size;    /* s1(1)'size */
:          int lower;           /* s1'first */
:          int upper;           /* s1'last */
:          int total;           /* s1'size */
:       } dv1;
:       int c;
:       unsigned s2_offset;
:       struct {
:          int element_size;    /* s2(1)'size */
:          int lower;           /* s2'first */
:          int upper;           /* s2'last */
:          int total;           /* s2'size */
:       } dv2;
:       union {
:          int fld1;
:          int fld2;
:       } n;
:    } *xrec_t;
: 
: void pass_record(xrec_t my)
: {
:    char *s1, *s2;
:    s1 = (char *)&(my->s1_offset);
:    s1 += my->s1_offset;
:    s2 = (char *)&(my->s2_offset);
:    s2 += my->s2_offset;
:    printf("p1 = %d\n",my->p1);
:    printf("p2 = %d\n",my->p2);
:    printf("b = %d\n",my->b);
:    printf("c = %d\n",my->c);
:    printf("fld1 = %d\n", my->n.fld1);
:    printf("s1 = %s\n",s1);   
:    printf("s2 = %s\n",s2);   
: }
: 
: void pass_string_array(char *s)
: {
:    printf("s = %s\n",s);   
: }
: 
: Sharon Shaw			
: CONVEX Systems Integration and Support