* 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