From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: * X-Spam-Status: No, score=1.3 required=5.0 tests=BAYES_00,INVALID_MSGID, MSGID_RANDY autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,1726119712bbda0d X-Google-Attributes: gid103376,public From: Ted Dennison Subject: Re: Interfacing to C non-void procedure with "out" parameters Date: 2000/01/14 Message-ID: <85ngl3$10s$1@nnrp1.deja.com>#1/1 X-Deja-AN: 572580724 References: <387f1c30.12554815@news.rdg.ac.uk> X-Http-Proxy: 1.0 x41.deja.com:80 (Squid/1.1.22) for client 204.48.27.130 Organization: Deja.com - Before you buy. X-Article-Creation-Date: Fri Jan 14 15:51:05 2000 GMT X-MyDeja-Info: XMYDJUIDtedennison Newsgroups: comp.lang.ada X-Http-User-Agent: Mozilla/4.6 [en] (WinNT; I) Date: 2000-01-14T00:00:00+00:00 List-Id: 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.