comp.lang.ada
 help / color / mirror / Atom feed
From: "REH" <me@you.com>
Subject: Re: How to pass two dimensional arrays to C
Date: Sat, 29 Jul 2006 04:19:14 GMT
Date: 2006-07-29T04:19:14+00:00	[thread overview]
Message-ID: <6lByg.12373$1Z5.8869@twister.nyroc.rr.com> (raw)
In-Reply-To: 1154119563.642347.13670@b28g2000cwb.googlegroups.com


"Jerry" <lanceboyle@qwest.net> 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





  parent reply	other threads:[~2006-07-29  4:19 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-07-28 11:06 How to pass two dimensional arrays to C Jerry
2006-07-28 12:27 ` Jeffrey Creem
2006-07-28 12:27 ` Dmitry A. Kazakov
2006-07-28 16:53 ` Adam Beneschan
2006-07-28 20:15 ` Jeffrey R. Carter
2006-07-28 20:46 ` Jerry
2006-07-28 21:14   ` Jeffrey Creem
2006-07-28 22:54   ` Björn Persson
2006-07-29  1:14     ` Jeffrey R. Carter
2006-07-29  7:11       ` Simon Wright
2006-07-29 22:12         ` Jeffrey R. Carter
2006-07-30 11:18           ` Simon Wright
2006-07-30 11:20           ` Simon Wright
2006-07-29  4:19   ` REH [this message]
2006-07-29  4:28     ` REH
2006-07-29  4:30       ` REH
2006-08-14  6:59     ` Dave Thompson
2006-07-29  5:47 ` REH
2006-08-02  8:20 ` Jerry
2006-08-02  9:03   ` Dmitry A. Kazakov
2006-08-02 10:22     ` Jerry
2006-08-02 18:25   ` Björn Persson
2006-08-05  1:03 ` Jerry
replies disabled

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