* 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 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
* 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
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