comp.lang.ada
 help / color / mirror / Atom feed
* Interfacing to C, output arrays
@ 1996-12-02  0:00 Simon Wright
  1996-12-02  0:00 ` Robert Dewar
  1996-12-10  0:00 ` Paul Chardon
  0 siblings, 2 replies; 5+ messages in thread
From: Simon Wright @ 1996-12-02  0:00 UTC (permalink / raw)



The code below shows an interface to a C function
  int accessor(int n, int* a);
which fills the n-element array a with data.

The code works just fine with Gnat 3.07 (OSF, Linux) but I think I may
be just 'lucky'.

The purpose of the subtype This_Arr is to make sure that the parameter
passed to the C code doesn't have any 'extraneous' constraint info at
the front (in fact, Gnat seems to pass the address of the first
element even to the Ada procedure anyway). Gnat warns that Result is
never assigned a value (that is, the Result out parameter to the Ada
procedure), so I'm concerned that another compiler might handle things
differently.

The Rationale doesn't cover the case of array parameters
(Interfaces.C.Pointers doesn't seem relevant here), but LRM B.3(70)
seems to indicate that I'm OK. Any thoughts?

--
with Interfaces.C;
package Inter is
  type Arr is array (Integer range <>) of Interfaces.C.Int;
  procedure Accessor (Result : out Arr);
end Inter;

package body Inter is
  procedure Accessor (Result : out Arr) is
    subtype This_Arr is Arr (Result'Range);
    function Accessor (N : Interfaces.C.Int;
		       Result : This_Arr) return Interfaces.C.Int;
    pragma Import (C, Accessor, "accessor");
    Count : Interfaces.C.Int;
  begin
    Count := Accessor (N => Result'Length, Result => Result);
  end Accessor;
end Inter;




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

* Re: Interfacing to C, output arrays
  1996-12-02  0:00 Interfacing to C, output arrays Simon Wright
@ 1996-12-02  0:00 ` Robert Dewar
  1996-12-03  0:00   ` Simon Wright
  1996-12-10  0:00 ` Paul Chardon
  1 sibling, 1 reply; 5+ messages in thread
From: Robert Dewar @ 1996-12-02  0:00 UTC (permalink / raw)



Simon asks about:

with Interfaces.C;
package Inter is
  type Arr is array (Integer range <>) of Interfaces.C.Int;
  procedure Accessor (Result : out Arr);
end Inter;

package body Inter is
  procedure Accessor (Result : out Arr) is
    subtype This_Arr is Arr (Result'Range);
    function Accessor (N : Interfaces.C.Int;
                       Result : This_Arr) return Interfaces.C.Int;
    pragma Import (C, Accessor, "accessor");
    Count : Interfaces.C.Int;
  begin
    Count := Accessor (N => Result'Length, Result => Result);
  end Accessor;
end Inter;

And he surmises that RM B.3(70) makes this safe.

Well, I certainly think that GNAT is right to output a warning here, at
the least it is very ugly to have a C routine modifying an in parameter,
and indeed I think a compiler would be within its rights (though perhaps
not well advised) to assume that the function call could not modify the
array.

It would be much cleaner to pass an access to the array or to use a
procedure call and make the parameter out or in out.

Also note that RM B.3(70) is only implementation advice, not a requirement.





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

* Re: Interfacing to C, output arrays
  1996-12-02  0:00 ` Robert Dewar
@ 1996-12-03  0:00   ` Simon Wright
  1996-12-07  0:00     ` Robert Dewar
  0 siblings, 1 reply; 5+ messages in thread
From: Simon Wright @ 1996-12-03  0:00 UTC (permalink / raw)



dewar@merv.cs.nyu.edu (Robert Dewar) writes:

> Simon asks about:
> 
> with Interfaces.C;
> package Inter is
>   type Arr is array (Integer range <>) of Interfaces.C.Int;
>   procedure Accessor (Result : out Arr);
> end Inter;
> 
> package body Inter is
>   procedure Accessor (Result : out Arr) is
>     subtype This_Arr is Arr (Result'Range);
>     function Accessor (N : Interfaces.C.Int;
>                        Result : This_Arr) return Interfaces.C.Int;
>     pragma Import (C, Accessor, "accessor");
>     Count : Interfaces.C.Int;
>   begin
>     Count := Accessor (N => Result'Length, Result => Result);
>   end Accessor;
> end Inter;
> 
> And he surmises that RM B.3(70) makes this safe.
> 
> Well, I certainly think that GNAT is right to output a warning here, at
> the least it is very ugly to have a C routine modifying an in parameter,
> and indeed I think a compiler would be within its rights (though perhaps
> not well advised) to assume that the function call could not modify the
> array.

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!

> It would be much cleaner to pass an access to the array or to use a
> procedure call and make the parameter out or in out.

The revised version below uses the access idea, at the cost of a copy.
Is this the only proper solution?

> Also note that RM B.3(70) is only implementation advice, not a requirement.

Point taken.

-- 
with Interfaces.C;
package Inter is
  type Arr is array (Integer range <>) of Interfaces.C.Int;
  procedure Accessor (Result : out Arr);
end Inter;

package body Inter is
  procedure Accessor (Result : out Arr) is
    subtype This_Arr is Arr (Result'Range);
    function Accessor (N : Interfaces.C.Int;
                       Result : access This_Arr) return Interfaces.C.Int;
    pragma Import (C, Accessor, "accessor");
    Count : Interfaces.C.Int;
    Res : aliased This_Arr;
  begin
    Count := Accessor (N => Result'Length, Result => Res'Access);
    Result := Res;
  end Accessor;
end Inter;




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

* Re: Interfacing to C, output arrays
  1996-12-03  0:00   ` Simon Wright
@ 1996-12-07  0:00     ` Robert Dewar
  0 siblings, 0 replies; 5+ messages in thread
From: Robert Dewar @ 1996-12-07  0:00 UTC (permalink / raw)



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!

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.

Probably your original dubious method of passing an in parameter will work.
We assume you have used a pragma Convention (C,..) for the type of Arr (or
the whole interfacing call is dubious), and it seems reasonable to assume
that any reasonable compiler will in fact pass the array by reference in
this case, in accordance with B.3(70):

   70  An Ada parameter of an array type with component 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.

So probably you should go back to your original scheme. If you like in GNAT
you can suppress the warning with a pragma Warnings (Off) just before the
line that gets a warning, and a pragma Warnings (On) right after.

Actually it is not only in the interfacing context that the inability to have
procedures with in out parameters can be annoying. Consider the definition
of Random in the RM, it modifies its generator argument. The only really
"correct" way to implement this function in Ada is to make the type Generator
be a controlled pointer into the heap, but this is nasty overkill, and nasty
implicit heap use, so if you look at the GNAT implementation, you will find
that it uses the same trick of "knowing" that an IN parameter is passed by
reference and hence can be modified. Of course the GNAT runtime library only
has to be portable to GNAT :-)

P.S. This is not intended to start a thread on whether it is a *good thing*
to allow in out or out parameters for functions. This point has been argued
to death more than once before, and the bottom line is that opinion is
strongly divided, but that there does not begin to be a consensus for making
this change to the language, and those who oppose it feel strongly. They
know quite well the arguments on the other side (which *I* strongly support),
but find them unconvincing. Fair enough -- that's why the change was not made,
but it does not stop it from being an annoying pain-in-the-neck!

P.P.S. In the realm of further non-portable solutions, note that GNAT's
unrestricted_access attribute could be used to avoid the copy in Simon's
truly portable solution, but then of course it would not be truly portable
any more :-)





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

* Re: Interfacing to C, output arrays
  1996-12-02  0:00 Interfacing to C, output arrays Simon Wright
  1996-12-02  0:00 ` Robert Dewar
@ 1996-12-10  0:00 ` Paul Chardon
  1 sibling, 0 replies; 5+ messages in thread
From: Paul Chardon @ 1996-12-10  0:00 UTC (permalink / raw)
  To: Simon Wright


Hello,

	I've got such problems similary problems handling C strings, and after
a moment I realize as for me that I've got a C problem, and not an Ada
problem. My proposal is the following one. The profile of you C function
mustn't it be :

	int accessor(int n, int* a[]);

Thus, the array parameter would be a real out one. Don't you think so ?

	Hope it will help you, Paul.




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

end of thread, other threads:[~1996-12-10  0:00 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1996-12-02  0:00 Interfacing to C, output arrays Simon Wright
1996-12-02  0:00 ` Robert Dewar
1996-12-03  0:00   ` Simon Wright
1996-12-07  0:00     ` Robert Dewar
1996-12-10  0:00 ` Paul Chardon

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