comp.lang.ada
 help / color / mirror / Atom feed
* Re: C-Ada Import of struct's -- Help
@ 1994-10-18 10:20 Bob Wells #402
  1994-10-18  9:58 ` David Emery
  0 siblings, 1 reply; 8+ messages in thread
From: Bob Wells #402 @ 1994-10-18 10:20 UTC (permalink / raw)


mmcnett@SPARC53.CS.UIUC.EDU writes .....

> I am having a problem on how to implement the following C structure in
> Ada.  The problem is I need to interface into a C procedure by passing
> it this structure so that it may update the information contained within
> it.  It will then return any changes made to the structure.  Much of
> the code in the C routine depends on this structure and I don't want to
> make changes to the procedure since many other routines also depend on
> the struct.
>
>
> C-structure:
>
> struct queue_noncyc_s {
>     char *debugname;          /* name for debugging purposes */
>     int length;               /* length (max items+1) of queue */
>     int first, last;          /* begin and end of queue */
>     Qitem *entries;           /* array[length] of entries */
> };
>
>
> Ada Code:
> procedure DDInitDisk (????????????); -- want to pass in the queue struct
> pragma IMPORT (C, DDInitDisk, "DDInitDisk");
>
> Thanks in advance,
>

G'day Michael,

After having interfaced many large C structures to Ada myself I
would suggest the following.

First define a trivial C function that will have as a parameter
a pointer to the desired structure.

#include queue_noncyc_s_defs.h

int DDInitDisk (queue_noncyc_s *queue)

{

      /* Code that does the updating of the queue structure */
      /* by calling the C function.                         */

      /* I've got it returning a status value so that you   */
      /* may return the status via the Ada I/O.             */

      /* By using a simple interface you can also verify    */
      /* what happens by using printf's to isolate the      */
      /* structure on the Ada side or the C side. Also both */
      /* before and after the call to the actual C updating */
      /* function which helps to isolate any errors.        */

      /* By using a pointer as the method of interface you  */
      /* are also making the interface much more portable.  */

}

Then "attack" the Ada types.

Look in the documentation for your compiler. Sometimes there is
defined, like for Verdix, a mapping of the Ada types to the C types.

package Queue_Interface is

  type Debug_Name_String is access String;

  -- As you haven't said what entries are, I'll assume something trivial
  -- like an array of integers,

  type Q_Item is array ( Natural range <> ) of Integer;
  type Q_Item_Ptr is access Q_Item;

  type Queue_Noncyc_S is
    record
      Debug_Name : Debug_Name_String;
      Length     : Integer;
      First      : Integer;
      Last       : Integer;
      Entries    : Q_Item_Ptr;
    end record;

  type Queue_Noncyc_S_Ptr is access Queue_Noncyc_S;

  -- Define an aggregate so that you can initialize the structure (so you
  -- won't get Constraint_Errors (via Access_Check) when you try to look
  -- at an unallocated variable.

  Init_Queue_Noncyc_S : Queue_Noncyc_S := ( Debug_Name => new String (1 .. 1),
                                            Length     => 0,
                                            First      => 0,
                                            Last       => 0,
                                            Entries    => new Q_Item (1 .. 1));

  -- Define your interfacing Ada function and the interfacing pragma.

  function DDInitDisk ( Queue : in Queue_Noncyc_S_Ptr )
    return Integer;

  pragma Interface ( C, DDInitDisk, "DDInit_Disk" );

  -- Declare your queue and initialize it.

  My_Queue : Queue_Noncyc_S_Ptr :=
    new Queue_Noncyc_S'(Init_Queue_Noncyc_S);

  -- You will have to define a function to search for the length of the
  -- debug string if you want to read it, so that you can declare a
  -- matching Ada debug string. (You would ordinarily have to define the
  -- same for the length of the entries array but as it's provided as a
  -- part of the structure then you don't need to). Or you could define a
  -- general C string to Ada string (and vice versa) function.

  function Debug_string_Length ( Str : Debug_Name_String ) return Integer;

end Queue_Interface;

  -----------------------

Then your calls to update the queue will be of the form

  Results := Queue_Interface.DDInitDisk ( Queue => My_Queue );

It is my experience that getting involved with discriminants gives
little benefits in interfacing. Keeping the interfacing object as
simple as possible makes the interface more robust and much more
easy to debug.

I hope this helps.

BTW The largest structures I have had to interface were complete X.400
headers with STAMINA (P77/P78) extensions and also containing ASN.1
representation structures.

@                   --------
@          ////  - ( G'day! )
@         (o o)     --------
@ ----oOO--(_)--OOo--------------------------------------------------------
  Bob Wells                             "For every action there is an equal
                                         and opposite government program."
@ INTERNET: wel@eurocontrol.de                 CompuServe:      100272,3004
@ The Ada WWW Server is http://lglwww.epfl.ch/Ada/                 Team Ada
@ For exciting Ada info enter 'finger wel@s4ecawel.eurocontrol.de'



^ permalink raw reply	[flat|nested] 8+ messages in thread
* Re: C-Ada Import of struct's -- Help
@ 1994-10-19 13:57 Bob Wells #402
  0 siblings, 0 replies; 8+ messages in thread
From: Bob Wells #402 @ 1994-10-19 13:57 UTC (permalink / raw)


G'day Dave,

Your absolutely correct about the access type/object/address
relationship. I forgot to add the use of a record rep clause on
the structure itself. The record rep. clause is used to force all
the record components into the seqence and location that you
want.

Dave, did you mean to include a record rep. clause aswell to
force the location of the record components into that as "requested"
by the C "world?"  Otherwise LRM 13.4.6 takes over and lets the
compiler "juggle" the components as it wants to.

I agree that use of system.addresses and address clauses is much
more portable.

I also did not make clear that the Ada/C string I/F subprogram
should take care of the conversions from and to the conventions in
the C and Ada worlds. BTW It was actually creating these I/F
subprograms while compiling under SunAda 1.0 where I had the
problems of strings, created using an allocator on an access type,
that had a STRING'FIRST value that was not 1! (I mentioned this
on c.l.a last year). The worst case I had was a STRING'FIRST of
23! BTW This is no longer the case in 1.1.

Robert Dewar is quite right that there is no defined requirement
that "a C string must be null terminated." You will need to see
what is happening with strings in your "C world" and then design
your Ada/C string conversion subprogram to comply.

I still stand by the use of the C wrapper program where the call
to the actual updating function is made. Also in the use of a
returned status value so that you can control your error handling/
reporting only in the Ada world.

As an extension to Dave Emery's comments on access types possibly
not containing an address I would be interested to know if any
compilers actually don't use addresses for their access types.
And for those compilers that don't, what do they use?

> In my (long and painful) experience interfacing Ada and C, I've found
> that the right approach is to bend over backwards and provide C with
> the exact thing it asks for (e.g. the address of the first element of
> a string is represented in Ada by STR(STR'FIRST)'ADDRESS).
> Fortunately, we can use the features of Ada to hide this ugliness
> within a package body, protecting the innocence of the programmer
> using the package...

BTW Dave, I totally agree with the above.

Concerning the method of function parameter passing, I thought that
"call by value" was strictly adhered to in C and that to achieve "call by
reference" a pointer must be used?

@                      --------
@          //// ----- ( G'day! )
@         (o o)        --------
@ ----oOO--(_)--OOo--------------------------------------------------------
  Bob Wells    "He looked at me as if I was a side dish he hadn't ordered."
@ INTERNET: wel@eurocontrol.de                 CompuServe:      100272,3004
@ The Ada WWW Server is http://lglwww.epfl.ch/Ada/                 Team Ada
@ For exciting Ada info enter 'finger wel@s4ecawel.eurocontrol.de'



^ permalink raw reply	[flat|nested] 8+ messages in thread
* C-Ada Import of struct's -- Help
@ 1994-10-18  3:34 mcnett michael david
  1994-10-18  9:48 ` David Emery
  0 siblings, 1 reply; 8+ messages in thread
From: mcnett michael david @ 1994-10-18  3:34 UTC (permalink / raw)



I am having a problem on how to implement the following C structure in
Ada.  The problem is I need to interface into a C procedure by passing
it this structure so that it may update the information contained within
it.  It will then return any changes made to the structure.  Much of 
the code in the C routine depends on this structure and I don't want to
make changes to the procedure since many other routines also depend on
the struct.


C-structure:

struct queue_noncyc_s {
    char *debugname;	      /* name for debugging purposes */
    int length;		      /* length (max items+1) of queue */
    int first, last;	      /* begin and end of queue */
    Qitem *entries;	      /* array[length] of entries */
};


Ada Code:
procedure DDInitDisk (????????????); -- want to pass in the queue struct
pragma IMPORT (C, DDInitDisk, "DDInitDisk");

Thanks in advance,

______________________________________________________________
Michael McNett               |
Graduate Student             |
University of Illinois       |
mmcnett@uiuc                 |




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

end of thread, other threads:[~1994-10-20  0:36 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1994-10-18 10:20 C-Ada Import of struct's -- Help Bob Wells #402
1994-10-18  9:58 ` David Emery
1994-10-18 19:11   ` Robert Dewar
1994-10-19 10:02     ` David Emery
1994-10-20  0:36     ` Keith Thompson @pulsar
  -- strict thread matches above, loose matches on Subject: below --
1994-10-19 13:57 Bob Wells #402
1994-10-18  3:34 mcnett michael david
1994-10-18  9:48 ` David Emery

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