From: Jerry <lan...@qw...> - 2008-09-04 21:11:08
|
On Sep 4, 2008, at 7:39 AM, Alan W. Irwin wrote: > On 2008-09-04 00:46-0700 Jerry wrote: > >> Can someone try this variation of the mock-example 19 on a 64-bit >> machine?I'm very hopeful that the problem is fixed. > > First ever success on my 64-bit platform! > > irwin@raven> . compile_and_run.shgcc-4.3 -c x19a_temp.adb > gcc-4.3 -c type_declaration.ads > gnatbind -x x19a_temp.ali > gnatlink x19a_temp.ali plmap.o > 0.00000000000000E+00 > 1.00000000000000E+00 > 2.00000000000000E+00 > 3.00000000000000E+00 > 4.00000000000000E+00 > 5.00000000000000E+00 > 6.00000000000000E+00 > 7.00000000000000E+00 > 8.00000000000000E+00 > 9.00000000000000E+00 > > Good work, Jerry, for figuring this out. > > I compared with the old code that didn't work, but did not > understand the > differences. Could you explain for those of us who do not > understand Ada > that well? What was unique about the bindings exercised by example > 19? Or > is this a general 64-bit issue which requires a number of changes > to the > bindings to fix? > > Alan > I' really glad to hear that the example works. I'll give full credit to the gurus at comp.lang.ada--all I had to do was to try to understand enough of their arcane explanations and speculations to put in the correct repair. The situation with Example 19 is unique within the PLplot world. The callback there is somewhat different in its structure from other callbacks in PLplot. Ada arrays carry with them information other than what is stored in the array proper. This includes the first index and last index (arrays don't have to begin with index 0--one of my gripes about many languages), the length, and the range. These are somewhat redundant but convenient in different situations. Say an array A is indexed from 3 to 7. Then A'First is 3, A'Last is 7, A'Length is 5, and A'Range is kind of like an enumeration and evaluates to 3 .. 7 where .. is a reserved word (I suppose). (Diversion: This makes writing loops in Ada a snap -- for i in A'Range loop bla bla bla end loop;. If the range changes, there is no need to re-write the loop. Plus, the loop index can be any enumerated type or subtype, so something like for Day_Of_Week in Monday .. Friday bla bla end loop; is fine. The loop variable is always locally defined and goes out of scope when the loop exits--no possibility of (mis)using loop variables in other places.) There are two ways to declare arrays in Ada--constrained arrays and unconstrained arrays. Constrained arrays have their attributes set in the declaration which might be 1 .. 31 for something related to days of the month. But there is often the need to have (subprograms that process) arrays with particular element types but with unknown (or variable) start and end indices. These array types can be declared with an open range (unconstrained array) but with a particular case taking on a particular range. Normally, Ada programs accept any (actual) version of the unconstrained array as a parameter as long as it has valid indices (attributes) and element type. The attributes come along for the ride as part of the actual parameter. The situation in Example 19 is that the calling chain (more or less) is Ada calling e.g. plmap which is in C and then plmap (or some other, deeper, C subprogram) calling the Ada program mapform19. The problem comes when the C subprogram calls the Ada mapform19--in the earlier simple example, for example, there is no way for it to tell mapform19 what x'First is when the formal parameter for x is an unconstrained array. The speculation from the guru list is that Ada _thinks_ it knows where x'First is stored and reads a value from that location. The read value is garbage but Ada proceeds anyway and is soon writing into the wrong place. The speculation is that the reason that it works on some machines and not others is that random memory locations frequently contain the value zero which is exactly the offset needed to make the calculation work correctly; if it is not zero, all bets are off. There was no speculation as to why 32-bit systems seem to work and 64-bit systems don't. There are other situations in the bindings which are similar to this but which do not contain all of the elements of Example 19. For example, in many places, Ada calls (or binds directly to) C or at least passes information to C. This is fine and actually part of the Ada language--the Ada argument list is simply made to match what C expects, typically with foo(x'Length, x). There are also places where in a callback C calls Ada but without passing an unconstrained array. I think that happens in e.g. plcont. It's the combination of passing an unconstrained array from C to Ada that causes trouble. The repair is straightforward if inelegant and possibly prone to cause aggravation to the occasional user. (In looking at the Ada code, remember that access types are like pointers.) I simply replaced the unconstrained array (type Real_Vector in the simple example) with a constrained array (subtype Constrained_Real_Vector) which is indexed from 0 to 20. I know that this size is adequate because I know that mapform19 requires only an array of size 10, as called from plmap--11 elements are wasted. This repair works because there is a known amount of memory allocated for x (21 elements) and the first index is 0 which is what C expects. In the actual PLplot code, I've hardwired the corresponding array subtype to have a range of 0 .. 2000. It is impossible for someone to compile a mapform-like function that uses malformed arrays x and y (just because that's the way Ada is) but they will be frustrated if they need to have more than 2001 elements in those arrays. (I'm open to suggestions for some number other than 2001.) There was some surprise on comp.lang.ada that this example even compiled. But the official Ada documentation (as read by some on that list) specifically says that passing unconstrained arrays to foreign languages is not necessarily supported. Hope that helps--probably more info than you wanted. I've submitted these changes to SVN so I hope to hear more good news. Jerry |