comp.lang.ada
 help / color / mirror / Atom feed
* Interfacing with C: access/out parameters
@ 2004-08-30 17:30 Jano
  2004-08-30 19:06 ` Jeffrey Carter
  2004-08-31  7:54 ` Egil H. H�vik
  0 siblings, 2 replies; 8+ messages in thread
From: Jano @ 2004-08-30 17:30 UTC (permalink / raw)


Hi,

I'm doing some C interfacing and I have a doubt about what's the proper 
way to do something "the Ada Way(tm)".

If I'm not mistaken, reading the relevant ARM section I see that C 
pointer parameters can be mapped either with access and out parameters.

I'm interfacing to some C functions which fill a data structure passed 
via pointer, and which return an error code I don't want to discard. So 
Firstly, I define a function like:

function Blah (Datum : access Data) return C.Int;
pragma Import (C, Blah);

since I can't use out mode in functions. Data is a record defined 
elsewhere with C convention.

Now, I would want to have a wrapper procedure more Ada-fied like:

Procedure Ada_Blah (Datum : out Data);
-- May raise some exception

And my doubt, finally, is: can I ensure somehow that Datum is passed by 
reference?, so I can do inside Ada_Blah [1]:

Helper : aliased Datum;
For Helper'Address use Datum'Address;
if Thin_Package.Blah (Helper'Access) = Error_Value then
    raise My_Error;
end if;

I know that tagged types are always passed by reference, but I fear that 
the tag will ruin the record structure. (My tests show indeed this is 
happening). It seems my only solution is to use a limited modifier. Am I 
right in that this would work properly in any compliant compiler? I'm 
ready to lose the copy operation.

I'd want to not use a wrapper type for the types implicated in this kind 
of functions... nor explicitely do a local copy, because the function 
may appear in code called at high frequency rates. Is this possible?

Thanks in advance,

A. Mosteo.

[1] This works with Gnat, but is it portable by some reason I ignore, or 
simply because Gnat uses reference passing for out record parameters?

P.s: A quite old thread here says:

"Simon says

   Yes, I quite understand that; the problem is that the C subprogram is
   a function and therefore can't be declared with an out parameter. I
   guess I could use the DEC pragma (valued_subprogram??), but that would
   be a tad implementation-dependent!

Deward says

Sure, it would be a bit implementation dependent. At the moment it would
only work on GNAT and DEC, though I would like to see this particular
pragma (Import_Valued_Procedure) implemented more widely, since it is
very useful in interfacing.

It is indeed the sad consequence of the rule forbidding out parameters 
in functions that the horrible copy in your suggested solution is the 
only truly portable way of doing things."

The last paragraph is discouraging. n
:(



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

* Re: Interfacing with C: access/out parameters
  2004-08-30 17:30 Interfacing with C: access/out parameters Jano
@ 2004-08-30 19:06 ` Jeffrey Carter
  2004-08-31  9:41   ` Alex R. Mosteo
  2004-08-31  7:54 ` Egil H. H�vik
  1 sibling, 1 reply; 8+ messages in thread
From: Jeffrey Carter @ 2004-08-30 19:06 UTC (permalink / raw)


Jano wrote:

> Helper : aliased Datum;
> For Helper'Address use Datum'Address;
> if Thin_Package.Blah (Helper'Access) = Error_Value then
>    raise My_Error;
> end if;

Assuming that you meant "Data" in the declaration of Helper, this is 
probably not a good way to do this. I would advise:

procedure Blah (Datum : out Data) is
    Helper : aliased Data;
begin -- Blah
    if Thin_Package.Blah (Helper'access) = Error_Value then
       raise My_Error;
    end if;

    Datum := Helper;
end Blah;

Before anyone starts complaining about the "inefficiency" of using a 
second variable and doing an assignment, I ask

1. What are the explicit timing requirements for this software?

2. Does it fail to meet these requirements?

3. If so, is eliminating this assignment the only way to meet the timing 
requirements?

I have never encountered SW where these could all be answered "Yes".

Probably you don't want your software to be using C-convention types for 
anything except the interface to C, so you'd want your thick binding to 
have an Ada-convention type for Datum, and assign the fields of Helper 
to it. Horrors! Multiple assignments!

-- 
Jeff Carter
"Now look, Col. Batguano, if that really is your name."
Dr. Strangelove
31




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

* Re: Interfacing with C: access/out parameters
  2004-08-30 17:30 Interfacing with C: access/out parameters Jano
  2004-08-30 19:06 ` Jeffrey Carter
@ 2004-08-31  7:54 ` Egil H. H�vik
  2004-08-31  9:11   ` Egil H. H�vik
  1 sibling, 1 reply; 8+ messages in thread
From: Egil H. H�vik @ 2004-08-31  7:54 UTC (permalink / raw)



"Jano" <notelacreas@porfavor.no> wrote in message
news:2ph6fjFkpsahU1@uni-berlin.de...
> Hi,
<snip>
>
> function Blah (Datum : access Data) return C.Int;
> pragma Import (C, Blah);
>
>
> Procedure Ada_Blah (Datum : out Data);
> -- May raise some exception
>
> And my doubt, finally, is: can I ensure somehow that Datum is passed by
> reference?, so I can do inside Ada_Blah [1]:
>
> Helper : aliased Datum;
> For Helper'Address use Datum'Address;
> if Thin_Package.Blah (Helper'Access) = Error_Value then
>     raise My_Error;
> end if;
>

Well, you say Data is a record type, so what's wrong with:

procedure Ada_Blah( Datum : out Data ) is
   function Blah( Datum : Data ) return C.int;
   pragma Import( C, Blah );
begin
   if Thin_Package.Blah(Datum) = Error_Value then
      raise My_Error;
   end if;
end Ada_Blah;


B.3(65): "An Ada function corresponds to a non-void C function"
B.3(69): "An Ada parameter of a record type T, of any mode, is passed as a
t* argument
   to a C function, where t is the C type corresponding to the Ada type T."


~egilhh





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

* Re: Interfacing with C: access/out parameters
  2004-08-31  7:54 ` Egil H. H�vik
@ 2004-08-31  9:11   ` Egil H. H�vik
  0 siblings, 0 replies; 8+ messages in thread
From: Egil H. H�vik @ 2004-08-31  9:11 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 1331 bytes --]


"Egil H. H�vik" <egil.harald.hoevik@REMOVEkongsberg.com> wrote in message
news:41342a34@193.71.169.73...
>
> "Jano" <notelacreas@porfavor.no> wrote in message
> news:2ph6fjFkpsahU1@uni-berlin.de...
> > Hi,
> <snip>
> >
> > function Blah (Datum : access Data) return C.Int;
> > pragma Import (C, Blah);
> >
> >
> > Procedure Ada_Blah (Datum : out Data);
> > -- May raise some exception
> >
> > And my doubt, finally, is: can I ensure somehow that Datum is passed by
> > reference?, so I can do inside Ada_Blah [1]:
> >
> > Helper : aliased Datum;
> > For Helper'Address use Datum'Address;
> > if Thin_Package.Blah (Helper'Access) = Error_Value then
> >     raise My_Error;
> > end if;
> >
>
> Well, you say Data is a record type, so what's wrong with:
>
> procedure Ada_Blah( Datum : out Data ) is
>    function Blah( Datum : Data ) return C.int;
>    pragma Import( C, Blah );
> begin
>    if Thin_Package.Blah(Datum) = Error_Value then

hmm... Copy-Paste error here... Should be Blah(Datum), minus Thin_Package


>       raise My_Error;
>    end if;
> end Ada_Blah;
>
>
> B.3(65): "An Ada function corresponds to a non-void C function"
> B.3(69): "An Ada parameter of a record type T, of any mode, is passed as a
> t* argument
>    to a C function, where t is the C type corresponding to the Ada type
T."
>
>
> ~egilhh
>
>





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

* Re: Interfacing with C: access/out parameters
  2004-08-30 19:06 ` Jeffrey Carter
@ 2004-08-31  9:41   ` Alex R. Mosteo
  2004-08-31  9:48     ` Alex R. Mosteo
  2004-08-31 18:26     ` Jeffrey Carter
  0 siblings, 2 replies; 8+ messages in thread
From: Alex R. Mosteo @ 2004-08-31  9:41 UTC (permalink / raw)


Jeffrey Carter wrote:
> 1. What are the explicit timing requirements for this software?
> 
> 2. Does it fail to meet these requirements?
> 
> 3. If so, is eliminating this assignment the only way to meet the timing 
> requirements?
> 
> I have never encountered SW where these could all be answered "Yes".
> 
> Probably you don't want your software to be using C-convention types for 
> anything except the interface to C, so you'd want your thick binding to 
> have an Ada-convention type for Datum, and assign the fields of Helper 
> to it. Horrors! Multiple assignments!

Thanks for the responses and sorry for the error in the example.

As you have already guessed, I want to get rid (if possible) of the 
copy. I can't say for sure that my soft answers "yes" to your three 
questions, but evaluate for yourself:

I'm writing a (initially thin) binding for the Player/Stage robot server 
(http://playerstage.sf.net). The function we are talking about is a 
generic message passing one were messages are normally little (up to 
8kB) but could be (almost) arbitrarily bigger. Message communication 
occurs at a configurable pace but the default is 10Khz if memory serves 
well.

As you see, is a function which is used often, by other, more 
specialized communication functions. Being a binding, any code using it 
would pass by this "bottleneck".

It's for these reasons that I would want to have the optimal high level 
solution, and eliminating the copy of the returned data seems a sensible 
  desire. There is that mentioned Import_Valued_Procedure in Gnat which 
addresses this Ada shortcoming, but talking about a binding, I want it 
to be totally portable if possible.

As per the C convention types all around the place, my intention is to 
build (if time permits) a thick binding over this thin binding, so that 
can be isolated later.

Further ideas? Is there anything definitely unadvisable in my original 
solution? (The one using limited/tagged types and 'Address).

Thanks!



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

* Re: Interfacing with C: access/out parameters
  2004-08-31  9:41   ` Alex R. Mosteo
@ 2004-08-31  9:48     ` Alex R. Mosteo
  2004-08-31 18:26     ` Jeffrey Carter
  1 sibling, 0 replies; 8+ messages in thread
From: Alex R. Mosteo @ 2004-08-31  9:48 UTC (permalink / raw)


Alex R. Mosteo wrote:
> I'm writing a (initially thin) binding for the Player/Stage robot server 
> (http://playerstage.sf.net). The function we are talking about is a 
> generic message passing one were messages are normally little (up to 
> 8kB) but could be (almost) arbitrarily bigger. Message communication 
> occurs at a configurable pace but the default is 10Khz if memory serves 
> well.

Ooops, two clarifications:

I'm the original poster, changed news installation.

The "generic message passing" doesn't refer to generics in the Ada 
slang. Just that any message is sent through this function.

Sorry for any misunderstanding.



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

* Re: Interfacing with C: access/out parameters
  2004-08-31  9:41   ` Alex R. Mosteo
  2004-08-31  9:48     ` Alex R. Mosteo
@ 2004-08-31 18:26     ` Jeffrey Carter
  2004-09-01  9:46       ` Alex R. Mosteo
  1 sibling, 1 reply; 8+ messages in thread
From: Jeffrey Carter @ 2004-08-31 18:26 UTC (permalink / raw)


Alex R. Mosteo wrote:

> It's for these reasons that I would want to have the optimal high level 
> solution, and eliminating the copy of the returned data seems a sensible 
>  desire. There is that mentioned Import_Valued_Procedure in Gnat which 
> addresses this Ada shortcoming, but talking about a binding, I want it 
> to be totally portable if possible.
> 
> As per the C convention types all around the place, my intention is to 
> build (if time permits) a thick binding over this thin binding, so that 
> can be isolated later.

Conversion to native Ada types will probably add assignment anyway.

> Further ideas? Is there anything definitely unadvisable in my original 
> solution? (The one using limited/tagged types and 'Address).

I would not advise using an overlay if you want to insure portability. 
For a convention C function, Ada automatically converts parameters of 
composite types to pointers (see Annex B), so you can "cheat" and use 
this fact to pass a pointer to your record. I've done a similar thing in 
a binding to fgets:

procedure Get (Item :    out String;
                Last :    out Natural;
                File : in     File_Handle := Standard_Input)
is
    Buffer : Char_Array (1 .. Item'Length + 1);
    -- May get a warning about Buffer never assigned a value
    Result : File_Handle; -- Dummy pointer

    function C_Get (Item : Char_Array; Length : Int; File : File_Handle)
    return File_Handle;
    pragma Import (C, C_Get, "fgets");
    -- Item should be "out", but since Import (C) will pass a pointer,
    -- this works.
begin -- Get
    Result := C_Get (Buffer, Buffer'Length, File);
    -- This fills Buffer, but Ada doesn't know that.

    if Result = null then
       raise EOF_Breached;
    end if;

    Extract : declare
       Value : constant String := To_Ada (Buffer);
    begin -- Extract
       if Value (Value'Last) = LF then -- Remove line terminator
          Last := Item'First + Value'Length - 2;
          Item (Item'First .. Last) :=
             Value (Value'First .. Value'Last - 1);
       else
          Last := Item'First + Value'Length - 1;
          Item (Item'First .. Last) := Value;
       end if;
    end Extract;
end Get;

-- 
Jeff Carter
"I'm particularly glad that these lovely children were
here today to hear that speech. Not only was it authentic
frontier gibberish, it expressed a courage little seen
in this day and age."
Blazing Saddles
88




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

* Re: Interfacing with C: access/out parameters
  2004-08-31 18:26     ` Jeffrey Carter
@ 2004-09-01  9:46       ` Alex R. Mosteo
  0 siblings, 0 replies; 8+ messages in thread
From: Alex R. Mosteo @ 2004-09-01  9:46 UTC (permalink / raw)


Jeffrey Carter wrote:

> I would not advise using an overlay if you want to insure portability. 
> For a convention C function, Ada automatically converts parameters of 
> composite types to pointers (see Annex B), so you can "cheat" and use 
> this fact to pass a pointer to your record. I've done a similar thing in 
> a binding to fgets:

I see. I was reticent to use this trick but if it is more portable I'll 
consider it again.

Thanks!



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

end of thread, other threads:[~2004-09-01  9:46 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-08-30 17:30 Interfacing with C: access/out parameters Jano
2004-08-30 19:06 ` Jeffrey Carter
2004-08-31  9:41   ` Alex R. Mosteo
2004-08-31  9:48     ` Alex R. Mosteo
2004-08-31 18:26     ` Jeffrey Carter
2004-09-01  9:46       ` Alex R. Mosteo
2004-08-31  7:54 ` Egil H. H�vik
2004-08-31  9:11   ` Egil H. H�vik

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