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