comp.lang.ada
 help / color / mirror / Atom feed
* Re: Rocket Science?
  1994-12-08 17:13 Rocket Science? Bob Crispen
@ 1994-12-08 16:23 ` David Emery
  0 siblings, 0 replies; 2+ messages in thread
From: David Emery @ 1994-12-08 16:23 UTC (permalink / raw)


The 'right way' to implement this is to use an enumeration type, but
to hide the mapping/representation.

There's no guarantee that AF_UNSPEC = 0 and/or AF_UNIX = 1 and/or
AF_UNSPEC > AF_UNIX.  In fact, I've seen situations where the ordering
of #define values was significantly different on different machines
for the same header file.

When you specify an enumeration type, you specify the ordering of the
values.  If the underlying C binding does not 'respect' this ordering
(and there's no particular requrement that it do so), then you're in
very serious trouble when you port the binding.  The package
specification has to change, and who knows the ramifications of this
change.  

Additionally, I've encountered problems with the size of enumeration
types.  Some implementations have rejected a size clause for an
enumeration type (I won't mention any names here, but it's a compiler
that otherwise has gotten a lot of 'respect'...) when the request size
is greater than what the compiler wants to allocate.  When this happens,
again you're in serious trouble.

So here's how I handle this particular situation:

from C:

#define AF_UNSPEC 0
#define AF_UNIX 1

(void) <some_C_call> (dom);
	int dom; 
{...};

package spec:
  package <whatever> is

    type Domains_And_Addresses_Families is (
      AF_UNSPEC,             -- Unspecified
      AF_UNIX,               -- Unix internal protocols...
	...);

    procedure <some_Ada_call> (the_domain : Domains_And_Addresses_Families);

  end <whatever>;


package body
  
  with C_Types;	-- Ada83 analogy to Ada95 package Interfaces.C
  package body <whatever> is

    package C_Interfaces is
      
      procedure <some_C_call> (dom : C_Types.int);
      pragma interface (C, <some_C_call>);

      LAST : constant C_Types.int := <value of last #define>;
      domains_to_int : constant array 	-- note anonymous array object here 
			(domains_and_adresses_families)
		of C_Types.int
		     :=  (AF_UNSPEC => 0,
			  AF_UNIX => 1,
			  ...);
      int_to_domains : constant array
			(C_Types.int range 0..last)
		of domains_and_adresses_families
		     := (0 => AF_UNSPEC,
			 1 => AF_UNIX,
			 ...);

    end C_Interfaces;

    procedure <some_Ada_call> (the_domain : Domains_And_Addresses_Families)
    is
    begin
      C_Interfaces.<some_C_call> 
		(dom => C_Interfaces.domains_to_int (the_domain));
    end <some_Ada_call>;

  end <whatever>;

The reason for the nested package in the body is so I can use the
exact C function name in the nested package without any overloading
problems for operations defined in the parent package.  (In Ada95,
would this be a good place for a private child package?)

If the integer values aren't contiguous, then you can write a simple
function 
	function int_to_domains (int : C_Types.int) 
	    return domains_and_addreses_families;
that does the reverse mapping.  The nice thing is that this change in
package C_interfaces is completely transparent to the rest of the
implementation.  (When used on the 'right hand side', array indexing
and function calls look the same.)

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

In summary, it's not hard to cobble up something that works for a
given Ada/C/API implementation.  It IS hard to define an Ada binding
that is portable (at least at the package specification level) across
multiple Ada/C/API trios.  I've been at this for 10 years, and I'm
still learning what works and what doesn't work.

				dave

p.s.  For more information on how to do Ada bindings "right" , see the
POSIX/Ada rationale (IEEE Std 1003.5-1992), and my paper in the
proceedings of TRI-Ada '90 on my prototype implementation of
POSIX/Ada.  Since the TRI-Ada '90 paper, I've learned a bunch more
tricks, etc, but I haven't had the chance to write a successor paper.
--
--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] 2+ messages in thread

* Re: Rocket Science?
@ 1994-12-08 17:13 Bob Crispen
  1994-12-08 16:23 ` David Emery
  0 siblings, 1 reply; 2+ messages in thread
From: Bob Crispen @ 1994-12-08 17:13 UTC (permalink / raw)


David Emery <emery@GOLDFINGER.MITRE.ORG> sez:

>>Developing Ada bindings isn't rocket science; it's well within the
>>capabilities of somebody with a year or two of Ada experience.
>
>Oh, I beg to differ.  There's an art to doing bindings.  I've seen
>(been victimized) by Ada bindings developed by junior people.  Right
>now I'm trying to rework some bindings that fit that pattern.  The guy
>did a nice job given his level of experience, but there are some
>serious problems that affect both usage and implementation.

OK, perhaps I was a little too cavalier.  Yup, it's altogether
possible to make a bad set of bindings.  I did a set of socket
bindings that has:

   type Domains_And_Address_Families is (
      AF_UNSPEC,             -- Unspecified
      AF_UNIX,               -- Unix internal protocols...

   for Domains_And_Address_Families use (
      AF_UNSPEC    =>  0,
      AF_UNIX      =>  1,...

   type Domains is new Domains_And_Address_Families;
   for Domains'size use 32;

   type Address_Families is new Domains_And_Address_Families;
   for Address_Families'size use 16;

which I think is a sensible way to approach this particular problem.

I suppose you *could* write:

   subtype Domains is Integer;
   subtype Address_Families is Short_Integer;

   AF_UNSPEC : constant := 0;

and so on, and technically that would count as bindings.

Perhaps I shouldn't have implied that writing good bindings is easy.
Writing good software is hard.  But I still think if you've got the
kind of genes that make you an eager Ada programmer instead of a
frustrated FORTRAN programmer doing Ada, you can probably put out a
decent set of bindings after a couple of years of experience.

At any rate, I've probably provided sufficient evidence that my own
level of writing bindings is so bad that I'm missing the whole point,
if that should be the case.
+-------------------------------+--------------------------------------+
| Bob Crispen                   |   Who will babysit the babysitters?  |
| crispen@foxy.hv.boeing.com    +--------------------------------------+
| (205) 461-3296                |Opinions expressed here are mine alone|
+-------------------------------+--------------------------------------+



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

end of thread, other threads:[~1994-12-08 17:13 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1994-12-08 17:13 Rocket Science? Bob Crispen
1994-12-08 16:23 ` David Emery

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