comp.lang.ada
 help / color / mirror / Atom feed
From: Ted Dennison <dennison@telepath.com>
Subject: Re: Interfacing to C non-void procedure with "out" parameters
Date: 2000/01/14
Date: 2000-01-14T00:00:00+00:00	[thread overview]
Message-ID: <85ngl3$10s$1@nnrp1.deja.com> (raw)
In-Reply-To: 387f1c30.12554815@news.rdg.ac.uk

In article <387f1c30.12554815@news.rdg.ac.uk>,
  S.J.Sangwine@Reading.ac.uk (Dr Steve Sangwine) wrote:
> Can anyone shed light on the issue of interfacing between Ada95 and C
> where there is a C procedure (non-void) which returns a result *and*
> modifies some of its parameters?

Sure; It can't happen. C routines can't modify their parameters. They
are all "in".

They can of course pass in *pointers* to objects and merrily modify the
pointed-to objects. You can do that with Ada functions too.

> I have a C procedure, for which I wanted to write an Ada95 spec, and
> import the C object code using pragma Import. Since the C procedure
> has a return result, I need an Ada function (or do I?). An Ada

Yup. Unless you are using Gnat. In that cause you could use pramga
Import_Valued_Procedure (I think I got the name right, but check).
However, that will render your binding unusable to other compilers.

> function must have parameters of mode 'in', implicitly or explicity,
> yet the C procedure will modify one or more of its parameters. To be
> safe, I wrote a wrapper procedure in C which had an extra parameter,
> and called this from Ada. The wrapper procedure called the real C
> procedure and returned the return result of the real C procedure in
> the extra parameter. That way the Ada spec can be a procedure and
> everything is watertight, but it is a nuisance to have this extra,
> trivial C wrapper procedure in between.

What I typically do is interface straight to the C routine in Ada, using
access or System.Address types where appropriate. Then I write a wrapper
routine in *Ada*, that provides a nice non-pointer Ada-like interface
(with status checks converted to exceptions, etc).

For instance, suppose we have the following (made up) C routine:

   int esGetValue (int key, const int *value);

The idea being that you pass in a key and get back a value for it. The
function returns 1 on success, 0 on failure.

On the Ada side, we'd much prefer to access this routine thusly:

   Get_Failed : exception; -- raised by Get_Value when the get fails

   function Get_Value (Key : Integer) return Integer;


First you interface to the routine to create your thin binding:

   function esGetValue (Key   : in Interfaces.C.Int;
                        Value : in System.Address
                       ) return Interfaces.C.Int;
   pragma Import (C, esGetValue, "esGetValue");

Note that for the "int *" parameter I used System.Address. This is not
officially portable, but in practice works on every normal platform. You
could instead use a type instantiated from Interfaces.C.Pointers for int
to achieve theoretical portability.

Finally we create our thick binding with the desired interface.

   function Get_Value (Key : Integer) return Integer is
      Value : aliased Interfaces.C.Int;
      use type Interfaces.C.Int; -- Give access to "=" operator
   begin
      if
        esGetValue
          (Key   => Interfaces.C.Int(Key),
           Value => Value
          ) = 0
      then
         raise Get_Failed;
      end if;
      return Integer(Value);
   end Get_Value;

--
T.E.D.

http://www.telepath.com/~dennison/Ted/TED.html


Sent via Deja.com http://www.deja.com/
Before you buy.




  parent reply	other threads:[~2000-01-14  0:00 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2000-01-14  0:00 Interfacing to C non-void procedure with "out" parameters Dr Steve Sangwine
2000-01-14  0:00 ` Alain Le Guennec
2000-01-14  0:00 ` Ted Dennison [this message]
2000-01-14  0:00   ` Jeff Carter
2000-01-14  0:00     ` Ted Dennison
2000-01-15  0:00       ` Jeff Carter
2000-01-17  0:00 ` Matthew Heaney
2000-01-18  0:00   ` Dr Steve Sangwine
replies disabled

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