comp.lang.ada
 help / color / mirror / Atom feed
From: Dave Thompson <david.thompson1@worldnet.att.net>
Subject: Re: How to pass two dimensional arrays to C
Date: Mon, 14 Aug 2006 06:59:41 GMT
Date: 2006-08-14T06:59:41+00:00	[thread overview]
Message-ID: <d440e2p7a3dkkn4g6dsvb5ck7v5klhlnha@4ax.com> (raw)
In-Reply-To: 6lByg.12373$1Z5.8869@twister.nyroc.rr.com

On Sat, 29 Jul 2006 04:19:14 GMT, "REH" <me@you.com> wrote:

> 
> "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 

Basically agree.

> 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.

Exactly.

> 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.

Almost. In C ary-of-ary and ary-of-ptr(-for-ary) are both X [I] [J].
In Ada array-of-array is X (I) (J) and so is array-of-access-to-array
since the dereference is implied; but true 2D array is X (I, J).

> 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 

Canonically, right.

> 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:
> 
But to be clear, NOT the way you just said (drop the first dimension).

> 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.
> 
Surely you mean someA (1,1) 'Address . 

> This makes the C code nicer, in that we can now just say P[1][2];
> 
Aside: You don't need the typedef's in C. They _don't_ create really
new types, only aliases/abbreviations. (But I'm fine with using them
for the pedagogical example, as they allow you to discuss different
points (!) separately.)

> 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 

As of C99 it can standardly, and although complete C99 implementations
are not common, some features including this one (called Variable
Length Arrays for the actual objects, and Variably Modified types for
some of the other types related to them like pointers) are becoming
common, and indeed were in GCC even before C99.

> yourself.  This is a pain and error-prone, but at least it is not 
> insurmountable.  For example (assume the element type is still int):
> 
Of course, doing this way (by hand) is still perfectly legal also.

> foo(void* P, int x, int y);
> 
Probably better unsigned /*int*/, or even better size_t. 
Dimensions cannot be negative, and cannot validly be zero; C doesn't
have Positive, but it does (almost) have Natural.

> Here we calculate P[1][2] thus:
> 
> const sx = sizeof(int) * y;
> const sy = sizeof(int);

const int (or better size_t) in C99; implicit int is (finally!) gone,
and types are NOT automatic like they are in Ada renames --
although a fairly similar feature is being considered for _C++_.

But per your correction the sizeof(int) factors aren't needed anyway.

> int* I = P;
> int v = P + sx * 1 + sy * 2;  *** again, remembering that the dimensions are 
> now zero-based.
> 

There's no need to pass the base pointer as void* and then convert it
to whatever*. Unless you are trying to make a type-generic utility
routine(s), and you can't really do that right in C, so barring
exigent circumstances I wouldn't confuse matters by trying.

> Messy, but doable.  You should create a function to do the indexing and 
> return the element.  If using C99, make it inline.
> 
I don't think it's worth making it a function. But then I've needed to
do manual-Ndim in enough languages (and systems) back to early FORTRAN
and BASIC that it's almost subconscious.

But I agree make it inline if you do. (Again actually supported in a
lot of compilers that don't support all of C99. But not all. But then
you can easily enough #define it away it necessary)

> 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.
> 

- David.Thompson1 at worldnet.att.net



  parent reply	other threads:[~2006-08-14  6:59 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
2006-07-29  4:28     ` REH
2006-07-29  4:30       ` REH
2006-08-14  6:59     ` Dave Thompson [this message]
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