comp.lang.ada
 help / color / mirror / Atom feed
* 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

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


Given
  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 */
  };

I come up with the following Ada data structure
  with System;
  package C_Types is
    type char_star is new System.address;
    type c_int is new integer;
  end C_Types;

  type queue_noncyc_s is record
    debugname : C_Types.char_star;
    length : C_Types.c_int;
    first, last  : C_Types.c_int;
    entries : System.address;  -- handle specially
  end record;
(There are 'standard tricks' for handling char * values.  See my paper
 in Tri-Ada '90.)

Now one problem is determining -how- the record is passed to C.  Some
C compilers support passing structs (required by ANSI C, I believe):
	int pass_struct (struct rec bar);
others do not, and you pass the address of the struct (Original K&R C):
	int pass_addr (struct rec *bar);
The latter case is more portable, and easier to represent.  

So, given our Ada type that we want to pass to C...
	q_rec : queue_noncyc_s;

To pass it to pass_addr() we have:
	function pass_addr (addr : system.address) return c_types.int;
	...
	pass_addr (q_rec'address);	-- pretty straightforward

A problem occurs with pass_struct().  I've seen cases where the C
compiler passes the structure, and other cases where it passes the
address of the structure.  And I've seen Ada compilers that did not
support the C compiler's choice.  

You'll either have to determine how your compiler does this, or,
better, write some wrapper code in C to reduce the problem to the
'known case'.  Write this C code, then call it from Ada.

	int pass_addr (bar)
		struct rec *bar;
	{	
		return pass_struct (*bar);	
		/*  calls original routine */
	};	

The Ada call for this is the as shown above.  

				dave
--
--The preceeding opinions do not necessarily reflect the opinions of
--The MITRE Corporation or its sponsors. 
-- "A good plan violently executed -NOW- is better than a perfect plan
--  next week"                                      George Patton
-- "Any damn fool can write a plan.  It's the execution that gets you
--  all screwed up"                              James Hollingsworth
-------------------------------------------------------------------------



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

* Re: C-Ada Import of struct's -- Help
  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
  0 siblings, 1 reply; 8+ messages in thread
From: David Emery @ 1994-10-18  9:58 UTC (permalink / raw)


I'm sorry, but Bob Wells' techniques are not very reliable/portable,
and will fail on many Ada compilers.

Bob makes the significant mistake of assuming that an Ada access type
has any relation to an address.  This is not a valid assumption on
some Ada compilers.  

Even when an access type is an address, it doesn't necessarily point
to the right thing.  By Definition in C, a "char *" representing a string
is the address of the first element of the string.  There's no
guarantee that an Ada access type points to the first element of the
string.  In fact, there is significant existing practice where the
access type points to a 'descriptor', which contains the address of
the first element of the string.  

The same reasoning holds true, even more so, for the other array type.  

Also, don't forget that a C string must be null-terminated.  Ada
provides no such guarantee for its strings.

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...

				dave
--
--The preceeding opinions do not necessarily reflect the opinions of
--The MITRE Corporation or its sponsors. 
-- "A good plan violently executed -NOW- is better than a perfect plan
--  next week"                                      George Patton
-- "Any damn fool can write a plan.  It's the execution that gets you
--  all screwed up"                              James Hollingsworth
-------------------------------------------------------------------------



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

* 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-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
  0 siblings, 2 replies; 8+ messages in thread
From: Robert Dewar @ 1994-10-18 19:11 UTC (permalink / raw)



"Also remember that a C string must be null terminated"

be careful not to confuse here, there is no such requirement in C. 
Certain C library routines (but by no means all) require strings to
be null terminated, and string constants are null terminated, but there
is no general requirement in C that corresponds to this quote.




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

* Re: C-Ada Import of struct's -- Help
  1994-10-18 19:11   ` Robert Dewar
@ 1994-10-19 10:02     ` David Emery
  1994-10-20  0:36     ` Keith Thompson @pulsar
  1 sibling, 0 replies; 8+ messages in thread
From: David Emery @ 1994-10-19 10:02 UTC (permalink / raw)


>be careful not to confuse here, there is no such requirement in C. 
>Certain C library routines (but by no means all) require strings to
>be null terminated, and string constants are null terminated, but there
>is no general requirement in C that corresponds to this quote.

True in theory, but in practice my experience is that "all strings" in
C need to be null-terminated.  A LOT of library routines and user code
will break if this is not followed, and 'lack of termination' is
clearly the exception, rather than the rule, in C practice.

					dave
--
--The preceeding opinions do not necessarily reflect the opinions of
--The MITRE Corporation or its sponsors. 
-- "A good plan violently executed -NOW- is better than a perfect plan
--  next week"                                      George Patton
-- "Any damn fool can write a plan.  It's the execution that gets you
--  all screwed up"                              James Hollingsworth
-------------------------------------------------------------------------



^ 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

* Re: C-Ada Import of struct's -- Help
  1994-10-18 19:11   ` Robert Dewar
  1994-10-19 10:02     ` David Emery
@ 1994-10-20  0:36     ` Keith Thompson @pulsar
  1 sibling, 0 replies; 8+ messages in thread
From: Keith Thompson @pulsar @ 1994-10-20  0:36 UTC (permalink / raw)


In <3816kn$n4e@schonberg.cs.nyu.edu> dewar@cs.nyu.edu (Robert Dewar) writes:
> "Also remember that a C string must be null terminated"
> 
> be careful not to confuse here, there is no such requirement in C. 
> Certain C library routines (but by no means all) require strings to
> be null terminated, and string constants are null terminated, but there
> is no general requirement in C that corresponds to this quote.

Not a requirement, but a definition.  Section 7.1.1 of the ANSI C
standard says

	A string is a contiguous sequence of characters terminated by
	and including the first null character.

This is merely a small confusion of terminology, though.  An Ada string
is simply an array of characters (of a particular type).  It is important
to remember that a C array of characters (char[]) may or may not contain
a "string"; a C pointer to [array of] character (char*) may or may not
point to a "string".

-- 
Keith Thompson (The_Other_Keith)  kst@alsys.com
TeleSoft^H^H^H^H^H^H^H^H Alsys, Inc.
10251 Vista Sorrento Parkway, Suite 300, San Diego, CA, USA, 92121-2718
/user/kst/.signature: I/O error (core dumped)



^ 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