comp.lang.ada
 help / color / mirror / Atom feed
* Variant Records from Ada to C
@ 1992-10-01 14:23 Randy Torres
  0 siblings, 0 replies; 3+ messages in thread
From: Randy Torres @ 1992-10-01 14:23 UTC (permalink / raw)


Would the following be safe.  I have a variant record and want to pass
it to a C routine.  I currently know what the data structures will look
like when past to C.  However, will this data structure change with
releases of Ada compilers, as well as different compilers?


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		

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Variant Records from Ada to C
@ 1992-10-02 15:17 WIS Program Group 
  0 siblings, 0 replies; 3+ messages in thread
From: WIS Program Group  @ 1992-10-02 15:17 UTC (permalink / raw)


In article <rtorres.717949389@mikey> rtorres@convex.com (Randy Torres) writes:
>
>Would the following be safe.  I have a variant record and want to pass
>it to a C routine.  I currently know what the data structures will look
>like when past to C.  However, will this data structure change with
>releases of Ada compilers, as well as different compilers?
>
>
>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		
>

I'll comment on the Ada part of things and suggest a couple of options.
No, I do not think this is a safe thing to try for the following reasons:

1.  Passing myrec.s1'address does not ensure that the address of the
    string itself will be passed.  You may end up with the address of
    the string descriptor or something similar.  It looks as if you
    have taken care of this in the c code, but you must ensure that
    this is the implementation of the string descriptor by the Ada
    compiler.  
 
    Usually I try to declare types that try to look like c declarations
    and then use those types.  One method that I think might work would
    be to pass myrec.s1(my_rec.s1'first)'address.  This would ensure 
    that the address of the first character of the string is passed
    to the called procedure.  In the called procedure you may then want
    to declare something along the lines of s1 *char.  The only thing you
    would then want to do is make sure that you make the string one 
    character longer than required and tack an ascii.nul on the end
    of the string.

2.  Passing myrec'address poses similar problems.  One thing you for 
    sure is that you do not know how the compiler defines the record,
    so some form of a representation specification would be recommended.
    However, I don't think that you will be able to write on for the 
    discriminant, or the two strings within the record (someone with more
    knowledge that I should respond to this part).  

Phil Dennis			pdennis@hfsi.com
HFSI, Wis Program Group, McLean, Va. 22102	(703) 827-3564

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Variant Records from Ada to C
@ 1992-10-02 19:01 agate!spool.mu.edu!sdd.hp.com!caen!deccrl!news.crl.dec.com!pa.dec.com!dat
  0 siblings, 0 replies; 3+ messages in thread
From: agate!spool.mu.edu!sdd.hp.com!caen!deccrl!news.crl.dec.com!pa.dec.com!dat @ 1992-10-02 19:01 UTC (permalink / raw)


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		

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~1992-10-02 19:01 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1992-10-02 19:01 Variant Records from Ada to C agate!spool.mu.edu!sdd.hp.com!caen!deccrl!news.crl.dec.com!pa.dec.com!dat
  -- strict thread matches above, loose matches on Subject: below --
1992-10-02 15:17 WIS Program Group 
1992-10-01 14:23 Randy Torres

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox