| Register | FAQ | Calendar | Search | Today's Posts | Mark Forums Read |
|
#21
| |||
| |||
| On Sep 3, 7:20*am, Adam Beneschan <a...@irvine.com> wrote: > > Several of us have pointed out that it's a bad idea to use an > unconstrained array type (i.e. Real_Vector) as a parameter to an > imported routine (or a routine with convention C), but the above code > still did it. > > * * * * * * * * * * * * * * * -- Adam In about a hundred cases in this same binding project, I have passed an unconstrained array (and its length) as a parameter to an Imported C subprogram without consequence--no warnings, no errors, no hangs--on several kinds of machines (32-bit and 64-bit). This seems to be allowed by ARM B.3.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." There is no restriction on unconstrained array types. The reason that I posted the modified code (mixed Ada and C) is that Randy's post indicated that it should work. In one instance (of the "hundred"), I "rename" one of these Imported C subprograms (it has two unconstrained arrays and their length as parameters). At the point of the "rename," GNAT generates two warnings, "foreign caller must pass bounds explicitly," and "type of argument "plfill.y" is unconstrained array." (plfill is the procedure name and y is one of the unconstrained arrays. A similar pair of warnings is generated for the other passed unconstrained array.) The purpose for renaming the procedure, which is originally declared as an Import with C conventions in another package (without warnings), is to allow the user to pass it as a callback to another Imported C subprogram. This works without problems. The difference between the two cases ([1] described above, herein, and [2] the code in mixed Ada and C that I posted earlier), is that in [1], both the called procedure and the callback procedure are written in C, and the in problematic code [2], the called subprogram is in C (plmap) but the callback (mapform19) is written in Ada, with C conventions. In a third scenario in the binding project [3], Ada successfully calls an Imported procedure written in C and passes a callback written in Ada with C conventions; this closely resembles the problematic code [2] except that in [3], the callback function is passed with 'Access and in [2] it is passed with 'Unrestricted_Access. Also, [3] doesn't pass an unconstrained array. (I don't see how to make [2] work with 'access without requiring the user to put the user-written callback into the binding package.) Jerry |
|
#22
| |||
| |||
| On Sep 3, 5:22 pm, Jerry <lancebo...@qwest.net> wrote: > On Sep 3, 7:20 am, Adam Beneschan <a...@irvine.com> wrote: > > > > > Several of us have pointed out that it's a bad idea to use an > > unconstrained array type (i.e. Real_Vector) as a parameter to an > > imported routine (or a routine with convention C), but the above code > > still did it. > > > -- Adam > > In about a hundred cases in this same binding project, I have passed > an unconstrained array (and its length) as a parameter to an Imported > C subprogram without consequence--no warnings, no errors, no hangs--on > several kinds of machines (32-bit and 64-bit). This seems to be > allowed by ARM B.3.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." > There is no restriction on unconstrained array types. This talks about passing an unconstrained array parameter *from* an Ada routine *to* a C function. You're doing more than that---you're having the C function pass the unconstrained array parameter back *to* an Ada routine, which the manual says nothing about. > The reason that I posted the modified code (mixed Ada and C) is that > Randy's post indicated that it should work. I think there must be a misunderstanding. In one of his posts he seemed to imply that it should work to pass an unconstrained array parameter to a C routine on all Ada compilers, but he then referred to the program as "unportable garbage". In another post he said that either the Ada compiler should document what should happen when an unconstrained array parameter is passed from C to Ada and implement it that way consistently (e.g. it should just decree that the lower bound is 0 and document it that way---but that's just one possible way of handling it), or reject the program. GNAT apparently doesn't do either so it's defective. The bug in GNAT, I believe, is that it compiles your Ada program in the first place---just my opinion. > In one instance (of the "hundred"), I "rename" one of these Imported C > subprograms (it has two unconstrained arrays and their length as > parameters). At the point of the "rename," GNAT generates two > warnings, "foreign caller must pass bounds explicitly," and "type of > argument "plfill.y" is unconstrained array." (plfill is the procedure > name and y is one of the unconstrained arrays. A similar pair of > warnings is generated for the other passed unconstrained array.) The > purpose for renaming the procedure, which is originally declared as an > Import with C conventions in another package (without warnings), is to > allow the user to pass it as a callback to another Imported C > subprogram. This works without problems. > > The difference between the two cases ([1] described above, herein, and > [2] the code in mixed Ada and C that I posted earlier), is that in > [1], both the called procedure and the callback procedure are written > in C, and the in problematic code [2], the called subprogram is in C > (plmap) but the callback (mapform19) is written in Ada, with C > conventions. Yup, this is not surprising at all to me. And if you go back and reread my earlier post, I believe I explained pretty thoroughly why this is happening, and also gave you a solution. Don't use an unconstrained array type in your callback routine. Period. You can use unconstrained arrays when calling C routines from Ada; but if you're going to call Ada routines from C, don't. -- Adam |
|
#23
| |||
| |||
| Jerry wrote: > > In about a hundred cases in this same binding project, I have passed > an unconstrained array (and its length) as a parameter to an Imported > C subprogram without consequence--no warnings, no errors, no hangs--on > several kinds of machines (32-bit and 64-bit). This seems to be > allowed by ARM B.3.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." > There is no restriction on unconstrained array types. Yes, but you're passing a pointer to an Ada convention-C subprogram to a C function, and C is calling that subprogram. The subprogram has a an unconstrained array parameter. This says nothing about what happens when C calls Ada. Ada needs to know what the lower bound of this array parameter is, and apparently your compiler is getting it wrong. Using a constrained array type with a lower bound of zero and an upper bound as large or larger than can occur would be the best choice for this situation. -- Jeff Carter "I fart in your general direction." Monty Python & the Holy Grail 05 |
|
#24
| |||
| |||
| "Adam Beneschan" <adam@irvine.com> wrote in message news:90006a35-e933-40f1-9a76-5698b0ce75d1@s20g2000prd.googlegroups.com... .... >> The difference between the two cases ([1] described above, herein, and >> [2] the code in mixed Ada and C that I posted earlier), is that in >> [1], both the called procedure and the callback procedure are written >> in C, and the in problematic code [2], the called subprogram is in C >> (plmap) but the callback (mapform19) is written in Ada, with C >> conventions. > > Yup, this is not surprising at all to me. And if you go back and > reread my earlier post, I believe I explained pretty thoroughly why > this is happening, and also gave you a solution. Don't use an > unconstrained array type in your callback routine. Period. You can > use unconstrained arrays when calling C routines from Ada; but if > you're going to call Ada routines from C, don't. Right. It is *only* OK to use an unconstrained array parameter in a subprogram that has pragma Import. It is *not* OK in any other context for C (objects, subprograms with Convention or Export pragmas, function returns of any kind). Your program is still using pragma Convention and you are still having C call Ada with an unconstrained parameter. You can't do that portably. I may have not looked carefully enough at your original program; I presumed that reason you were using pragma Convention was so that you could write the routine in Ada, and that it would be replaced by pragma Import in the real program. If that was wrong, I probably mislead you. Randy. |
|
#25
| |||
| |||
| On Sep 3, 6:31 pm, "Jeffrey R. Carter" <spam.jrcarter....@spam.acm.org> wrote: > Ada needs to know what the lower bound of this array parameter is, and > apparently your compiler is getting it wrong. One other thing that probably ought to be mentioned: It's possible that the compiler is trying to determine the lower bound by looking at some memory location where it expects the lower bound to be, but in reality (since the Ada routine is being called from C) contains a random value previously used for something else. My experience is that memory locations with random values contain zero a high percentage of the time, so it would make sense that the program would happen to work on some platforms, or on some targets. If I understood the original post correctly, the program seemed to be working on some platforms but not others, and it could well be because of this random factor. It doesn't mean the compiler or the program were correct on those platforms. > Using a constrained array type or subtype, I think. > with a lower bound of zero and an upper bound as large or larger than can occur > would be the best choice for this situation. -- Adam |
|
#26
| |||
| |||
| [ calling an Ada function from C with an array argument ] Isn't this a case, where package Interfaces.C.Pointers is appropriate to use? (Despite the name, it seems mostly to be concerned with C-style "arrays".) Greetings, Jacob -- "Never trust a statistic you have not falsified yourself." |
|
#27
| |||
| |||
| Jerry <lanceboyle@qwest.net> writes: > The difference between the two cases ([1] described above, herein, and > [2] the code in mixed Ada and C that I posted earlier), is that in > [1], both the called procedure and the callback procedure are written > in C, and the in problematic code [2], the called subprogram is in C > (plmap) but the callback (mapform19) is written in Ada, with C > conventions. Referring to [2], you also need to be careful (GNAT & VxWorks at least) if the C calling thread isn't an Ada task; the Ada code expects the VxWorks TCB to contain a pointer to auxiliary Ada RTS structures. Call GNAT.Threads.Register_Thread (as early as possible in the called Ada subprogram, I guess! before it needs the secondary stack, for example) |
|
#28
| |||
| |||
| Jeff Carter writes: > Ada needs to know what the lower bound of this array parameter is, and > apparently your compiler is getting it wrong. Using a constrained array type > with a lower bound of zero and an upper bound as large or larger than can occur > would be the best choice for this situation. I would actually use a local, constrained array type of exactly the required length: procedure Ada_Callback (Length : in Natural; Array_Address : in System.Address); pragma Convention (C, Ada_Callback); procedure Ada_Callback (Length : in Natural; Array_Address : in System.Address) is type Constrained_Array_Subtype is array (1 .. Length) of Long_Float; X : Constrained_Array_Subtype; for X'Address use Array_Address; pragma Import (Ada, X); -- disable default initialization begin ... end Ada_Callback; I know using System.Address may seem unholy at first sight but this implementation is explicit about what it does -- dangerous things with an address received from the unsafe "external world" outside the control of the compiler. Comments? -- Ludovic Brenta. |
|
#29
| |||
| |||
| On Sep 5, 1:17 am, Ludovic Brenta <ludo...@ludovic-brenta.org> wrote: > Jeff Carter writes: > > Ada needs to know what the lower bound of this array parameter is, and > > apparently your compiler is getting it wrong. Using a constrained array type > > with a lower bound of zero and an upper bound as large or larger than can occur > > would be the best choice for this situation. > > I would actually use a local, constrained array type of exactly the > required length: > > procedure Ada_Callback (Length : in Natural; Array_Address : in > System.Address); > pragma Convention (C, Ada_Callback); > > procedure Ada_Callback (Length : in Natural; Array_Address : in > System.Address) is > type Constrained_Array_Subtype is array (1 .. Length) of > Long_Float; or array (0 .. Length - 1)... > X : Constrained_Array_Subtype; > for X'Address use Array_Address; > pragma Import (Ada, X); -- disable default initialization > begin > ... > end Ada_Callback; > > I know using System.Address may seem unholy at first sight but this > implementation is explicit about what it does -- dangerous things with > an address received from the unsafe "external world" outside the > control of the compiler. > > Comments? Doing it your way has a better chance of being portable. Earlier, others and I have recommended using a constrained array subtype (with a large upper bound) as a parameter, and I'd guess that will have the desired effect on most compilers, but you never know---sometimes compilers have unexpected ways of doing things. If you're sure that a System.Address will look just like a C (void *) or (double *) type, and will be passed in the same way, then using a System.Address parameter will make pretty sure that things will work right. -- Adam |
|
#30
| |||
| |||
| Ludovic Brenta wrote: > > I know using System.Address may seem unholy at first sight but this > implementation is explicit about what it does -- dangerous things with > an address received from the unsafe "external world" outside the > control of the compiler. > > Comments? There's no guarantee that a C pointer and Ada's System.Address are the same thing. Of course, to be safe, you shouldn't use Integer, Long_Float, or any other type not declared in Interfaces.C and its children, or otherwise declared convention C. So really this should be something like type Double_Ptr is access all Interfaces.C.Double; pragma Convention (C, Double_Ptr); procedure Ada_Callback (Length : Interfaces.C.Int; First_Component : Double_Ptr); pragma Convention (C, Ada_Callback); And then mess with pointer arithmetic (: But a constrained array type is just as safe: type C_List is array (Interfaces.C.Int range 0 .. Interfaces.C.Int'Last) of aliased Interfaces.C.Double; pragma Convention (C, C_List); procedure Ada_Callback (Length : Interfaces.C.Int; List : C_List); pragma Convention (C, Ada_Callback); And much easier to use. -- Jeff Carter "You me on the head hitted." Never Give a Sucker an Even Break 108 |
![]() |
| Thread Tools | |
| Display Modes | |
In an effort to better serve ads to our visitors, cookies are used on objectmix.com. For more information, check out our Privacy Policy.