comp.lang.ada
 help / color / mirror / Atom feed
* Interfacing C type, unconstrained array with record
@ 2010-10-16 17:35 Ron Wills
  2010-10-16 18:36 ` Dmitry A. Kazakov
  0 siblings, 1 reply; 13+ messages in thread
From: Ron Wills @ 2010-10-16 17:35 UTC (permalink / raw)


Hi all

I've started learning Ada and started porting some software I had in C/
C++ as a learning exercise. The software uses SDL, so I started a thin
wrapper around it. I've been very successful with it, but with the
exception of the palette structure which in C is defined as:

typedef struct {
  int ncolors;
  SDL_Color colors[]; // Actually is SDL_Color *colors but this is how
it is laid out in memory
} SDL_Palette;

In Ada I'm trying to do something like:

type SDL_Color is
  record
    r, g, b, unused : Uint8;
  end;
type SDL_Color_Array is array(Positive range <>) of Color;
type SDL_Palette is
  record
    ncolors : Integer;
    colors : SDL_Color_Array;
  end;

 Now Ada (GNAT) won't compile this because the colors component is
unconstrained, which is understandable. I've been googling for a
couple of days for a way of modeling this in Ada and still having
access to all the colors in the colors component. In other SDL
interface implementations, all I've seen is that the colors component
is made into a type of "Dummy" component and made more or less
useless. I've also been combing the reference manual, but nothing I've
noticed seems to solve this issue. I'm sure I'm not the only one that
has come across this problem and was wondering what solutions are
available.

Thanks



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Interfacing C type, unconstrained array with record
  2010-10-16 17:35 Interfacing C type, unconstrained array with record Ron Wills
@ 2010-10-16 18:36 ` Dmitry A. Kazakov
  2010-10-16 19:19   ` Ron Wills
  2010-10-16 21:41   ` Robert A Duff
  0 siblings, 2 replies; 13+ messages in thread
From: Dmitry A. Kazakov @ 2010-10-16 18:36 UTC (permalink / raw)


On Sat, 16 Oct 2010 10:35:39 -0700 (PDT), Ron Wills wrote:

> Hi all
> 
> I've started learning Ada and started porting some software I had in C/
> C++ as a learning exercise. The software uses SDL, so I started a thin
> wrapper around it. I've been very successful with it, but with the
> exception of the palette structure which in C is defined as:
> 
> typedef struct {
>   int ncolors;
>   SDL_Color colors[]; // Actually is SDL_Color *colors but this is how
> it is laid out in memory
> } SDL_Palette;
> 
> In Ada I'm trying to do something like:
> 
> type SDL_Color is
>   record
>     r, g, b, unused : Uint8;
>   end;
> type SDL_Color_Array is array(Positive range <>) of Color;
> type SDL_Palette is
>   record
>     ncolors : Integer;
>     colors : SDL_Color_Array;
>   end;
> 
> Now Ada (GNAT) won't compile this because the colors component is
> unconstrained, which is understandable. I've been googling for a
> couple of days for a way of modeling this in Ada and still having
> access to all the colors in the colors component. In other SDL
> interface implementations, all I've seen is that the colors component
> is made into a type of "Dummy" component and made more or less
> useless. I've also been combing the reference manual, but nothing I've
> noticed seems to solve this issue. I'm sure I'm not the only one that
> has come across this problem and was wondering what solutions are
> available.

You need a flat array, e.g.

   with Interfaces;  use Interfaces;
   with Interfaces.C;  use Interfaces.C;
      ...
   type SDL_Color is record
      R, G, B, Unused : Unsigned_8;
   end record;
   pragma Convention (C, SDL_Color);
   type SDL_Color_Array is array (Positive) of aliased SDL_Color;
   pragma Convention (C, SDL_Color_Array);
   type SDL_Palette is record
      N_Colors : Int;
      Colors   : SDL_Color_Array;
   end record;
   pragma Convention (C, SDL_Palette);

Now, you cannot directly declare a SDL_Palette variable, because it is too
large. You should do it as you would do in C, i.e. allocate some amount of
memory and then set structure pointer to it. You do not need 'new' or
access types in Ada. It can be on the stack like this:

   with System.Storage_Elements;  use System.Storage_Elements;
      ...
   Raw_Memory : Storage_Array (1..1_024); -- Memory
   Palette    : SDL_Palette;
   for Palette'Address use Raw_Memory'Address;
begin
   Palette.N_Colors := 20;

Of course computing memory size from N_Colors is up to you (as in C).

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Interfacing C type, unconstrained array with record
  2010-10-16 18:36 ` Dmitry A. Kazakov
@ 2010-10-16 19:19   ` Ron Wills
  2010-10-16 22:15     ` Jeffrey Carter
  2010-10-17  8:35     ` Dmitry A. Kazakov
  2010-10-16 21:41   ` Robert A Duff
  1 sibling, 2 replies; 13+ messages in thread
From: Ron Wills @ 2010-10-16 19:19 UTC (permalink / raw)


On Oct 16, 12:36 pm, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
wrote:
> On Sat, 16 Oct 2010 10:35:39 -0700 (PDT), Ron Wills wrote:
> > Hi all
>
> > I've started learning Ada and started porting some software I had in C/
> > C++ as a learning exercise. The software uses SDL, so I started a thin
> > wrapper around it. I've been very successful with it, but with the
> > exception of the palette structure which in C is defined as:
>
> > typedef struct {
> >   int ncolors;
> >   SDL_Color colors[]; // Actually is SDL_Color *colors but this is how
> > it is laid out in memory
> > } SDL_Palette;
>
> > In Ada I'm trying to do something like:
>
> > type SDL_Color is
> >   record
> >     r, g, b, unused : Uint8;
> >   end;
> > type SDL_Color_Array is array(Positive range <>) of Color;
> > type SDL_Palette is
> >   record
> >     ncolors : Integer;
> >     colors : SDL_Color_Array;
> >   end;
>
> > Now Ada (GNAT) won't compile this because the colors component is
> > unconstrained, which is understandable. I've been googling for a
> > couple of days for a way of modeling this in Ada and still having
> > access to all the colors in the colors component. In other SDL
> > interface implementations, all I've seen is that the colors component
> > is made into a type of "Dummy" component and made more or less
> > useless. I've also been combing the reference manual, but nothing I've
> > noticed seems to solve this issue. I'm sure I'm not the only one that
> > has come across this problem and was wondering what solutions are
> > available.
>
> You need a flat array, e.g.
>
>    with Interfaces;  use Interfaces;
>    with Interfaces.C;  use Interfaces.C;
>       ...
>    type SDL_Color is record
>       R, G, B, Unused : Unsigned_8;
>    end record;
>    pragma Convention (C, SDL_Color);
>    type SDL_Color_Array is array (Positive) of aliased SDL_Color;
>    pragma Convention (C, SDL_Color_Array);
>    type SDL_Palette is record
>       N_Colors : Int;
>       Colors   : SDL_Color_Array;
>    end record;
>    pragma Convention (C, SDL_Palette);

The "pragma Convention" did the trick! I must say, Ada is the one
language I've encountered that seems to have the largest learning
curve because of the most cryptic references I ever seen ;)

> Now, you cannot directly declare a SDL_Palette variable, because it is too
> large. You should do it as you would do in C, i.e. allocate some amount of
> memory and then set structure pointer to it. You do not need 'new' or
> access types in Ada. It can be on the stack like this:
>
>    with System.Storage_Elements;  use System.Storage_Elements;
>       ...
>    Raw_Memory : Storage_Array (1..1_024); -- Memory
>    Palette    : SDL_Palette;
>    for Palette'Address use Raw_Memory'Address;
> begin
>    Palette.N_Colors := 20;
>
> Of course computing memory size from N_Colors is up to you (as in C).

Thanks for the tip, but I don't actually need to allocate any palette
records (this should never be done). The palette is a read-only field
within the pixel information structure of a surface. I just need this
record definition to define the constant access pointer to be able to
access the palette information.

Many thanks, now I move forward again :D

> --
> Regards,
> Dmitry A. Kazakovhttp://www.dmitry-kazakov.de




^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Interfacing C type, unconstrained array with record
  2010-10-16 18:36 ` Dmitry A. Kazakov
  2010-10-16 19:19   ` Ron Wills
@ 2010-10-16 21:41   ` Robert A Duff
  2010-10-16 23:34     ` tmoran
                       ` (2 more replies)
  1 sibling, 3 replies; 13+ messages in thread
From: Robert A Duff @ 2010-10-16 21:41 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:

> You need a flat array, e.g.
>
>    with Interfaces;  use Interfaces;
>    with Interfaces.C;  use Interfaces.C;

I'd probably write:

    with Interfaces.C;  use Interfaces;

and then refer to C.int instead of Int.
No big deal.

>    type SDL_Color is record
>       R, G, B, Unused : Unsigned_8;
>    end record;
>    pragma Convention (C, SDL_Color);
>    type SDL_Color_Array is array (Positive) of aliased SDL_Color;

I think you want this indexed by the same type as N_Colors.
And why does it need to have aliased components?
So perhaps:

    type SDL_Color_Array is array (Int range 1..1_000_000) of SDL_Color;

>    pragma Convention (C, SDL_Color_Array);
>    type SDL_Palette is record
>       N_Colors : Int;
>       Colors   : SDL_Color_Array;
>    end record;
>    pragma Convention (C, SDL_Palette);
>
> Now, you cannot directly declare a SDL_Palette variable, because it is too
> large. You should do it as you would do in C, i.e. allocate some amount of
> memory and then set structure pointer to it. You do not need 'new' or
> access types in Ada. It can be on the stack like this:
>
>    with System.Storage_Elements;  use System.Storage_Elements;
>       ...
>    Raw_Memory : Storage_Array (1..1_024); -- Memory
>    Palette    : SDL_Palette;
>    for Palette'Address use Raw_Memory'Address;

I think you need to worry about alignment here.
Perhaps:

    pragma Assert(SDL_Palette'Alignment = C.int'Alignment);
    for Raw_Memory'Alignment use C.int'Alignment;

> begin
>    Palette.N_Colors := 20;
>
> Of course computing memory size from N_Colors is up to you (as in C).

You might want to say:

    Colors: SDL_Color_Array renames Palette.Colors(1..Palette.N_Colors);

and then refer to components of Colors, so you get array bounds checking.

- Bob



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Interfacing C type, unconstrained array with record
  2010-10-16 19:19   ` Ron Wills
@ 2010-10-16 22:15     ` Jeffrey Carter
  2010-10-17 10:20       ` Simon Wright
  2010-10-17  8:35     ` Dmitry A. Kazakov
  1 sibling, 1 reply; 13+ messages in thread
From: Jeffrey Carter @ 2010-10-16 22:15 UTC (permalink / raw)


On 10/16/2010 12:19 PM, Ron Wills wrote:
>
> The "pragma Convention" did the trick! I must say, Ada is the one
> language I've encountered that seems to have the largest learning
> curve because of the most cryptic references I ever seen ;)

You should probably finish learning Ada before trying to do stuff like 
interfacing with C. Then you'd realize the "cryptic references" are all due to C.

-- 
Jeff Carter
"Crucifixion's a doddle."
Monty Python's Life of Brian
82



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Interfacing C type, unconstrained array with record
  2010-10-16 21:41   ` Robert A Duff
@ 2010-10-16 23:34     ` tmoran
  2010-10-17  6:59     ` J-P. Rosen
  2010-10-17  7:45     ` Dmitry A. Kazakov
  2 siblings, 0 replies; 13+ messages in thread
From: tmoran @ 2010-10-16 23:34 UTC (permalink / raw)


In this particular simple (and common) case, how about translating

> typedef struct {
>   int ncolors;
>   SDL_Color colors[]; // Actually is SDL_Color *colors but this is how
> it is laid out in memory
> } SDL_Palette;

to

type SDL_Palette(ncolors : interfaces.c.int) is record
  colors : SDL_Color_Array(1 .. ncolors);
end record;
for SDL_Palette use record
  ncolors at 0 range 0 .. 31;
end record;

I don't understand the following comment.  "colors" here is actually
an array, not a pointer, right?
>   SDL_Color colors[]; // Actually is SDL_Color *colors but this is how
> it is laid out in memory



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Interfacing C type, unconstrained array with record
  2010-10-16 21:41   ` Robert A Duff
  2010-10-16 23:34     ` tmoran
@ 2010-10-17  6:59     ` J-P. Rosen
  2010-10-17 12:34       ` Robert A Duff
  2010-10-17  7:45     ` Dmitry A. Kazakov
  2 siblings, 1 reply; 13+ messages in thread
From: J-P. Rosen @ 2010-10-17  6:59 UTC (permalink / raw)


Le 16/10/2010 23:41, Robert A Duff a �crit :
> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
> 
>> You need a flat array, e.g.
>>
>>    with Interfaces;  use Interfaces;
>>    with Interfaces.C;  use Interfaces.C;
> 
> I'd probably write:
> 
>     with Interfaces.C;  use Interfaces;
> 
> and then refer to C.int instead of Int.
> No big deal.
> 
Nitpicking: nothing prevents you from writing C.int even in the presence
of a use clause for Interfaces.C. Although I am quite liberal in using
use clauses, I do that quite often when I feel it is more readable.

-- 
---------------------------------------------------------
           J-P. Rosen (rosen@adalog.fr)
Adalog a d�m�nag� / Adalog has moved:
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Interfacing C type, unconstrained array with record
  2010-10-16 21:41   ` Robert A Duff
  2010-10-16 23:34     ` tmoran
  2010-10-17  6:59     ` J-P. Rosen
@ 2010-10-17  7:45     ` Dmitry A. Kazakov
  2 siblings, 0 replies; 13+ messages in thread
From: Dmitry A. Kazakov @ 2010-10-17  7:45 UTC (permalink / raw)


On Sat, 16 Oct 2010 17:41:40 -0400, Robert A Duff wrote:

> and then refer to C.int instead of Int.

There is no integer but int, and Stroustrup is its prophet! (:-))

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Interfacing C type, unconstrained array with record
  2010-10-16 19:19   ` Ron Wills
  2010-10-16 22:15     ` Jeffrey Carter
@ 2010-10-17  8:35     ` Dmitry A. Kazakov
  2010-10-17 12:30       ` Robert A Duff
  1 sibling, 1 reply; 13+ messages in thread
From: Dmitry A. Kazakov @ 2010-10-17  8:35 UTC (permalink / raw)


On Sat, 16 Oct 2010 12:19:18 -0700 (PDT), Ron Wills wrote:

> The "pragma Convention" did the trick! I must say, Ada is the one
> language I've encountered that seems to have the largest learning
> curve because of the most cryptic references I ever seen ;)

What you are doing is interfacing to another language. That is not Ada, but
system programming. If you think pragma Convention cryptic, well, what
about reading the compiler manual for call stack frame format details and
implementing that using Assembler code insertions? (:-))

P.S. to dear ARG members. Why discrimnants cannot be mapped onto components
of a C structure. I mean making OK this:

   type Vector is array (size_t range <>) of Whatever;
� �pragma Convention (C, Vector);
� �type Constrained (Size : size_t) is record
   � � �List� : Vector (1..Size);
� �end record;
� �pragma Convention (C, Constrained);

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Interfacing C type, unconstrained array with record
  2010-10-16 22:15     ` Jeffrey Carter
@ 2010-10-17 10:20       ` Simon Wright
  2010-10-17 12:38         ` Robert A Duff
  0 siblings, 1 reply; 13+ messages in thread
From: Simon Wright @ 2010-10-17 10:20 UTC (permalink / raw)


Jeffrey Carter <spam.jrcarter.not@spam.not.acm.org> writes:

> On 10/16/2010 12:19 PM, Ron Wills wrote:
>>
>> The "pragma Convention" did the trick! I must say, Ada is the one
>> language I've encountered that seems to have the largest learning
>> curve because of the most cryptic references I ever seen ;)
>
> You should probably finish learning Ada before trying to do stuff like
> interfacing with C. Then you'd realize the "cryptic references" are
> all due to C.

I agree about the cryptic references being because of C, but .. people
normally start on a new language because they have a project in mind and
it seems like a possible fit; and if that project involves interfacing
with C, that's where they're going to begin.

Personally (but them I've been doing this for a while) I found the ARM
sections on interfacing pragmas
(http://www.adaic.com/standards/05rm/html/RM-B-1.html) and interfacing
with C and C++ (http://www.adaic.com/standards/05rm/html/RM-B-3.html)
clear -- except that I started at the second, and only found the link to
the first half-way down the page.



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Interfacing C type, unconstrained array with record
  2010-10-17  8:35     ` Dmitry A. Kazakov
@ 2010-10-17 12:30       ` Robert A Duff
  0 siblings, 0 replies; 13+ messages in thread
From: Robert A Duff @ 2010-10-17 12:30 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:

> On Sat, 16 Oct 2010 12:19:18 -0700 (PDT), Ron Wills wrote:
>
>> The "pragma Convention" did the trick! I must say, Ada is the one
>> language I've encountered that seems to have the largest learning
>> curve because of the most cryptic references I ever seen ;)
>
> What you are doing is interfacing to another language. That is not Ada, but
> system programming. If you think pragma Convention cryptic, well, what
> about reading the compiler manual for call stack frame format details and
> implementing that using Assembler code insertions? (:-))

Good point.  And what about reading the C standard to find all
the good features for interfacing to Ada (or to any other
language)?  That's easy -- there are no such features!

> P.S. to dear ARG members. Why discrimnants cannot be mapped onto components
> of a C structure. I mean making OK this:
>
>    type Vector is array (size_t range <>) of Whatever;
> � �pragma Convention (C, Vector);
> � �type Constrained (Size : size_t) is record
>    � � �List� : Vector (1..Size);
> � �end record;
> � �pragma Convention (C, Constrained);

Well, in fact I think that will work in GNAT, although it
will warn about the fact that C doesn't have discriminants.

But this is tricky.  The C code depends on the fact that the
List component comes last.  There is no such requirement
in Ada that discriminant-dependent fields come last
(either in the declaration, or in the memory layout).

What if there were two discriminants, and two discriminant-dependent
arrays?  That doesn't match anything on the C side.

Many compilers use extra dope when there are discriminants
or unconstrained arrays.  Ada 83 didn't have very good
support for interfacing -- most of this stuff was invented
for Ada 95.  But by that time, compilers already existed,
and the compiler writers didn't want to change the "dope".
For example, I know of one compiler that would store
the size (in bytes) of the above record (in addition to
the Size field, which is the length of that array).

Whether that's a good idea is arguable, but it has the
advantage that block "=" and ":=" don't have to
calculate the size in bytes.  And it's just a special
case of storing the offset of each discriminant-dependent
component (to avoid recalculating those) -- the size is
just the offset of the end.

(By the way, I prefer to use "size" to refer to memory
sizes, measured in bits, bytes, words, or whatever,
and use "length" to refer to array lengths, measured
in number of components.  The latter is a higher-level
concept.)

Anyway, I guess the real answer to your question is,
C doesn't have discriminants, so nobody thought
it would be a good idea to require interfacing
discriminants to something in C.  It could make
sense, but only in very limited cases.  Compilers
are allowed to support it, but there's no portable
(language defined) support.

- Bob



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Interfacing C type, unconstrained array with record
  2010-10-17  6:59     ` J-P. Rosen
@ 2010-10-17 12:34       ` Robert A Duff
  0 siblings, 0 replies; 13+ messages in thread
From: Robert A Duff @ 2010-10-17 12:34 UTC (permalink / raw)


"J-P. Rosen" <rosen@adalog.fr> writes:

> Nitpicking: nothing prevents you from writing C.int even in the presence
> of a use clause for Interfaces.C.

True, but I rarely take advantage of that, and I prefer
to say X.Y or Y consistently, not both in the same
package.

I fixed a bug in GNAT a few days ago, where I ran across
code that mixed X.Y and Y, because somebody thought
X.Y was more readable, but somebody else just refered
to Y because Y happened to be directly visible.  No big deal,
but the code looked odd to me.

> ...Although I am quite liberal in using
> use clauses, I do that quite often when I feel it is more readable.

- Bob



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Interfacing C type, unconstrained array with record
  2010-10-17 10:20       ` Simon Wright
@ 2010-10-17 12:38         ` Robert A Duff
  0 siblings, 0 replies; 13+ messages in thread
From: Robert A Duff @ 2010-10-17 12:38 UTC (permalink / raw)


Simon Wright <simon@pushface.org> writes:

> I agree about the cryptic references being because of C, but .. people
> normally start on a new language because they have a project in mind and
> it seems like a possible fit; and if that project involves interfacing
> with C, that's where they're going to begin.

True, but interfacing between languages is inherently complicated,
and inherently dangerous.  Ada has pretty good support in this
area compared to most other languages (most of which entirely
ignore the issue).  That makes Ada more complicated, but also
more useful.

- Bob



^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2010-10-17 12:38 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-10-16 17:35 Interfacing C type, unconstrained array with record Ron Wills
2010-10-16 18:36 ` Dmitry A. Kazakov
2010-10-16 19:19   ` Ron Wills
2010-10-16 22:15     ` Jeffrey Carter
2010-10-17 10:20       ` Simon Wright
2010-10-17 12:38         ` Robert A Duff
2010-10-17  8:35     ` Dmitry A. Kazakov
2010-10-17 12:30       ` Robert A Duff
2010-10-16 21:41   ` Robert A Duff
2010-10-16 23:34     ` tmoran
2010-10-17  6:59     ` J-P. Rosen
2010-10-17 12:34       ` Robert A Duff
2010-10-17  7:45     ` Dmitry A. Kazakov

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