From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Thread: 103376,6b3a3c920575b35a X-Google-Attributes: gid103376,public X-Google-Language: ENGLISH,ASCII-7-bit Path: g2news2.google.com!news4.google.com!border1.nntp.dca.giganews.com!nntp.giganews.com!newsfeed2.easynews.com!newsfeed1.easynews.com!easynews.com!easynews!newspeer1.nwr.nac.net!news.maxwell.syr.edu!news-rtr.nyroc.rr.com!news-out.nyroc.rr.com!twister.nyroc.rr.com.POSTED!53ab2750!not-for-mail From: "REH" Newsgroups: comp.lang.ada References: <1154084819.088112.325730@p79g2000cwp.googlegroups.com> <1154119563.642347.13670@b28g2000cwb.googlegroups.com> Subject: Re: How to pass two dimensional arrays to C X-Priority: 3 X-MSMail-Priority: Normal X-Newsreader: Microsoft Outlook Express 6.00.2900.2869 X-RFC2646: Format=Flowed; Original X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.2869 Message-ID: <6lByg.12373$1Z5.8869@twister.nyroc.rr.com> Date: Sat, 29 Jul 2006 04:19:14 GMT NNTP-Posting-Host: 69.205.134.80 X-Complaints-To: abuse@rr.com X-Trace: twister.nyroc.rr.com 1154146754 69.205.134.80 (Sat, 29 Jul 2006 00:19:14 EDT) NNTP-Posting-Date: Sat, 29 Jul 2006 00:19:14 EDT Organization: Road Runner Xref: g2news2.google.com comp.lang.ada:6006 Date: 2006-07-29T04:19:14+00:00 List-Id: "Jerry" wrote in message news:1154119563.642347.13670@b28g2000cwb.googlegroups.com... > Thanks for everyone's comments. I have thin bindings to PLplot nearly > complete except for this nagging 2D array thing. (I also have a partial > thick binding plus some easy-to-use one-line plotters as well.) > With respect to everyone, I believe you being led a little astray. C does have multidimensional arrays. The problems they are at a lower level than Ada's array, and less convenient. For you to call C, and send it an array from Ada, you have to deal with a few issues: 1. When used as a function parameter, an array will "decay" to a pointer to the first element of the array. This can be inconvenient because information about the size and dimensions of the array are lost. Arrays are not "first class" citizens. You can make them so by wrapping them in structs, but this only works if you know the dimensions at compile type. So, that is limited use. 2. What "type" of array? There can be a couple of different types in C, because of their close relationship to pointers. One type is the simple contiguous array: a[x][y]; Though, one might argue that this is not a 2d array, but an array of arrays. That's just semantics, and doesn't matter. The elements will be layed out the same assuming the elements are the same and row major ordering is used (so, for Fortran, you would reverse the dimensions, since it uses column major ordering). The second type is called a jagged array, which is an array of pointers. You can simulate this form in Ada using an array of access types to the second dimension. And for both languages, an access to and element of the jagged array uses that same syntax as a 2d array. 3. Are the dimensions constant? As long as all but the first dimension is constant, it is simply a matter of giving C a pointer to an object whose type is your array type minus the first dimension (again, assume the memory is layed out the same). So, if in Ada we have (ignoring necessay pragmas and/or rep. specs.): type A is array (1 .. 10, 1 .. 10) of Interface.C.int; type pA is access all A; we can map this in C several ways. One easy to understand way is: typedef A[10][10]; void foo(A* P); this would map to an Ada procedure thus: procedure foo(P : in pA); This has the advantage of C "knowing" the dimensions, but is inconvenient because because P has to be dereferenced before dimensions may be applied: (*P)[1][2]; *** remember that the dimensions now in C, so the ranges for both are 0 to 9. Another way would be: typedef A[10]; void foo(A* P); To map this, we must either use System.Address and lose type safety or change A to be an array of array and use an access type to the second dimension array (messy). procedure foo(P : in System.Address); call foo with A[1,1]'Address. This makes the C code nicer, in that we can now just say P[1][2]; Both methods assume the dimensions are constant. If only the first dimension is variable, use the second method above, and send C that dimension via another parameter. If both dimensions are variable, this is more problematic because C cannot define array types with variable dimensions. All this means is that you have to calculate the indexing yourself. This is a pain and error-prone, but at least it is not insurmountable. For example (assume the element type is still int): foo(void* P, int x, int y); Here we calculate P[1][2] thus: const sx = sizeof(int) * y; const sy = sizeof(int); int* I = P; int v = P + sx * 1 + sy * 2; *** again, remembering that the dimensions are now zero-based. Messy, but doable. You should create a function to do the indexing and return the element. If using C99, make it inline. Jagged arrays are even messier. These are just arrays of pointers. They allow the creation of arrays where the second dimension is of varying length. The problem is that C will not intrinsically know the lengths, and thus you will probably have to give it an array of lengths as a second parameter. But, most likely, if you are going from Ada to C, you aren't dealing with these. I probably made some mistakes above in my haste, but you should get the gist. REH