comp.lang.ada
 help / color / mirror / Atom feed
* Re: More C
       [not found] <vhizotrc4x7.fsf@grotte.ifi.uio.no>
  2000-01-28  0:00 ` More C tmoran
@ 2000-01-28  0:00 ` Jeff Carter
  2000-01-28  0:00 ` Gautier
  2000-01-30  0:00 ` Nick Roberts
  3 siblings, 0 replies; 11+ messages in thread
From: Jeff Carter @ 2000-01-28  0:00 UTC (permalink / raw)


Jan Kroken wrote:
> I have the following C structs
> 
> typedef struct {
>         Uint8 r;
>         Uint8 g;
>         Uint8 b;
>         Uint8 unused;
> } SDL_Color;
> 
> typedef struct {
>         int       ncolors; /* number of colors */
>         SDL_Color *colors; /* array of colors */
> } SDL_Palette;
> 
> and have included them in Ada as
> 
> type SDL_Color is record
>         R, G, B, Unused: C.Unsigned_Char;
> end record;

Note the comment that this is an array. The best way to treat this in
Ada is probably as an array:

type SDL_Palette is record
   Num_Colors : C.Int;
   Address_Of_Color_Array : System.Address;
end record;

Given:

   Palette : SDL_Palette;

containing data from C, use

type Color_Set is array (C.Int range <>) of SDL_Color;

Colors : Color_Set (1 .. Palette.Num_Colors);
for Colors'Address use Palette.Address_Of_Color_Array;

That only answers 1 of your 2 questions, I'm afraid.

-- 
Jeff Carter
"We burst our pimples at you."
Monty Python & the Holy Grail




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

* Re: More C
       [not found] <vhizotrc4x7.fsf@grotte.ifi.uio.no>
@ 2000-01-28  0:00 ` tmoran
  2000-01-28  0:00   ` David Starner
  2000-01-28  0:00 ` Jeff Carter
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 11+ messages in thread
From: tmoran @ 2000-01-28  0:00 UTC (permalink / raw)


type SDL_Color is record
        R, G, B: C.Unsigned_Char;
end record;
for SDL_Color'size use 4*8;
for SDL_Color use record
  R at 0 range 0 .. 7;
  G at 1 range 0 .. 7;
  B at 2 range 0 .. 7;
end record;
-- You might want to replace C.Unsigned_Char with something like
-- type Intensity is range 0 .. 255;
-- for Intensity'size use 8;

type SDL_Color_Access is access SDL_Color;

type Color_List is array(C.Int range <>) of aliased SDL_Color;
type Color_List_Access is access all Color_List;

type SDL_Palette is record
        Number_Of_Colors: C.Int;
        Colors: Color_List_Access;
end record;

I presume you really want Colors to point to a Color_List, not to a
single color.  Note that Colors will point to a list of N colors,
where N may, or may not, equal Number_Of_Colors.  So you can either
ignore Number_Of_Colors (using Palette.Colors.all'length if you need
the count of colors in the list) or you can have your "Indexed"
function do a check that "Index in 1 ..  Number_Of_Colors" or
"Index in 0 ..  Number_Of_Colors-1" or whatever, in addition to the
automatic index check.

function Indexed_Color_Access(Palette: SDL_Palette;
                              Index: C.Int) return SDL_Color_Access is
begin
  if Index in 1 .. Palette.Number_Of_Colors then
      return Palette.Colors(Index)'access;
  else
      raise Constraint_Error;
  end if;
end Indexed_Color_Access;

Depending on what you're doing, you might want:

function Indexed_Color(Palette: SDL_Palette;
                       Index: C.Int) return SDL_Color is
begin
  if Index in 1 .. Palette.Number_Of_Colors then
      return Palette.Colors(Index);
  else
      raise Constraint_Error;
  end if;
end Indexed_Color;

In both of the above functions, if you really want to have
  type SDL_Palette_Access is access SDL_Palette;
and have the functions take a parameter of
    Palette : SDL_Palette_Access;
instead of
    Palette : SDL_Palette;
then the rest of the function still works as written because
    Palette.Number_Of_Colors  and   Palette.Colors(Index)
are equivalent to
    (Palette.all).Number_Of_Colors  and   (Palette.all).Colors(Index)

Note that I've changed Color_Array to Palette, since an SDL Palette
is more than just an array.

If the structure of SDL_Palette as a count and a pointer isn't forced
on you, of course, it would be simpler to just use the Color_List
array (perhaps renaming Color_List to Palette).  Then just refer to
   Color_Array(Index)
where, e.g.,
   Color_Array : Color_List(1 .. 17);

If you really must match the memory layout of the C SDL_Palette,

type Arbitrary_Color_List is array(C.Int range) of aliased SDL_Color;
type Arbitrary_Color_List_Access is access all Color_List;

type SDL_Palette is record
        Number_Of_Colors: C.Int;
        Colors: Arbitrary_Color_List_Access;
end record;

is probably your best bet.  You then have to do your own index
checking, just as in C, and you'll want a representation clause.

It's possible in Ada to do dangerous things like address arithmetic
to look at storage a certain number of bytes beyond where a
particular SDL_Color is stored, but it should rarely be needed.
If it is really needed, look at packages System.Storage_Elements
and System.Address_To_Access_Conversions

For some examples of records laid out to communicate with Windows
about colors and bitmaps, see Claw (internal package Colors) and
Claw.Bitmaps in the $0 version of Claw at www.rrsoftware.com




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

* Re: More C
       [not found] <vhizotrc4x7.fsf@grotte.ifi.uio.no>
  2000-01-28  0:00 ` More C tmoran
  2000-01-28  0:00 ` Jeff Carter
@ 2000-01-28  0:00 ` Gautier
  2000-01-30  0:00 ` Nick Roberts
  3 siblings, 0 replies; 11+ messages in thread
From: Gautier @ 2000-01-28  0:00 UTC (permalink / raw)


If it can help (e.g. for your buffer questions, you can take a look
at code in svga02x4.zip, link below).

-- 
Gautier

_____\\________________\_______\_________
http://members.xoom.com/gdemont/gsoft.htm




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

* Re: More C
  2000-01-28  0:00 ` More C tmoran
@ 2000-01-28  0:00   ` David Starner
  2000-01-28  0:00     ` Pascal Obry
  0 siblings, 1 reply; 11+ messages in thread
From: David Starner @ 2000-01-28  0:00 UTC (permalink / raw)


On Fri, 28 Jan 2000 05:14:39 GMT, tmoran@bix.com <tmoran@bix.com> wrote:
>type SDL_Palette is record
>        Number_Of_Colors: C.Int;
>        Colors: Color_List_Access;
>end record;
>
>I presume you really want Colors to point to a Color_List, not to a
>single color.  Note that Colors will point to a list of N colors,
>where N may, or may not, equal Number_Of_Colors.  So you can either
>ignore Number_Of_Colors (using Palette.Colors.all'length if you need
>the count of colors in the list) or you can have your "Indexed"
>function do a check that "Index in 1 ..  Number_Of_Colors" or
>"Index in 0 ..  Number_Of_Colors-1" or whatever, in addition to the
>automatic index check.

This seems wrong. What gives Ada the information about how long that
list is? Looking at the C structure, the reason why Number_Of_Colors
was stored there is so that the length is known, and it is not
stored anywhere else.

-- 
David Starner - dstarner98@aasaa.ofe.org
If you wish to strive for peace of soul then believe; 
if you wish to be a devotee of truth, then inquire.
   -- Friedrich Nietzsche




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

* Re: More C
  2000-01-28  0:00     ` Pascal Obry
@ 2000-01-28  0:00       ` David Starner
  2000-01-28  0:00         ` tmoran
  0 siblings, 1 reply; 11+ messages in thread
From: David Starner @ 2000-01-28  0:00 UTC (permalink / raw)


On Fri, 28 Jan 2000 09:36:15 +0100, Pascal Obry <p.obry@der.edf.fr> wrote:
>David,
>
>The answer to your question was in the message you quoted!
>
>To know the number of colors use : Palette.Colors'Length (.all is
>not required here I think).
>
>You can also iterate through the table using:
>
>   for K in Palette.Colors'Range loop
>      ...
>   end loop;
>
>Did I missed something ?

We have a similar structure
struct bob {
   char num_chars_in_b;
   char *b; /* array */
};

In memory (assuming 8 bit pointers) we have

num_chars_in_b
|  pointer    array
|  |          |
03 20 ......  01 10 10 23 58 20 48 . . .

The only place in that memory where it tells you the length of the
array is num_chars_in_b. No matter how you translate that structure
into Ada, Ada can't give you the length of the array independent of
num_chars_in_b, because it doesn't have the information. Or so
I understand it.

-- 
David Starner - dstarner98@aasaa.ofe.org
If you wish to strive for peace of soul then believe; 
if you wish to be a devotee of truth, then inquire.
   -- Friedrich Nietzsche




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

* Re: More C
  2000-01-28  0:00       ` David Starner
@ 2000-01-28  0:00         ` tmoran
  0 siblings, 0 replies; 11+ messages in thread
From: tmoran @ 2000-01-28  0:00 UTC (permalink / raw)


>In memory (assuming 8 bit pointers) we have
>
>num_chars_in_b
>|  pointer    array
>|  |          |
>03 20 ......  01 10 10 23 58 20 48 . . .
>
>The only place in that memory where it tells you the length of the
>array is num_chars_in_b. No matter how you translate that structure
>into Ada, Ada can't give you the length of the array independent of
>num_chars_in_b, because it doesn't have the information. Or so
>I understand it.

Quite so.  But in the message I posted it said:
>I presume you really want Colors to point to a Color_List, not to a
>single color.  Note that Colors will point to a list of N colors,
>where N may, or may not, equal Number_Of_Colors.

in which case the pointer points to an array and the compiler
either knows its bounds or knows where to look to find its
bounds (if they are dynamic).

The case you have is:

>If you really must match the memory layout of the C SDL_Palette,
>
>type Arbitrary_Color_List is array(C.Int range) of aliased SDL_Color;
>type Arbitrary_Color_List_Access is access all Color_List;
>
>type SDL_Palette is record
>        Number_Of_Colors: C.Int;
>        Colors: Arbitrary_Color_List_Access;
>end record;
>
>is probably your best bet.  You then have to do your own index
>checking, just as in C, and you'll want a representation clause.

Since the compiler knows the (unchanging) bounds, here all of C.Int,
it needn't put them in memory anywhere and can set the pointer
to the array Colors to be the identical bits to a pointer
to the first element of Colors, which matches the C layout.
There's no guarantee it will do this, so you must experiment to
see what happens and put big signs around warning of danger, but
it will probably work.  An alternative, more work but likely
more safely portable, is the suggestion from Jeff Carter of

>type SDL_Palette is record
>   Num_Colors : C.Int;
>   Address_Of_Color_Array : System.Address;
>end record;
>
>Given:
>
>   Palette : SDL_Palette;
>
>containing data from C, use
>
>type Color_Set is array (C.Int range <>) of SDL_Color;
>
>Colors : Color_Set (1 .. Palette.Num_Colors);
>for Colors'Address use Palette.Address_Of_Color_Array;

Note, however, that a C pointer is not necessarily the same
as an Ada System.Address (consider various i86 memory models)
so that probably ought to be modified to

type SDL_Palette is record
   Num_Colors : C.Int;
   C_Access_Of_Color_Array : Interfaces.C.Strings.char_array_access;
end record;

and then use System.Address_To_Access_Conversions to convert
C_Access_Of_Color_Array to a System.Address to use in the
  for Colors'Address use the_address_from_C_Access_Of_Color_Array;

PS. I should have said
  type Arbitrary_Color_List is array(C.Int range 0 .. C.Int'last)
  of aliased SDL_Color;
since you probably want index 0 (or maybe 1), rather than C.Int'first,
to indicate the first element.




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

* Re: More C
  2000-01-28  0:00   ` David Starner
@ 2000-01-28  0:00     ` Pascal Obry
  2000-01-28  0:00       ` David Starner
  0 siblings, 1 reply; 11+ messages in thread
From: Pascal Obry @ 2000-01-28  0:00 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 1076 bytes --]


David,

The answer to your question was in the message you quoted!

To know the number of colors use : Palette.Colors'Length (.all is
not required here I think).

You can also iterate through the table using:

   for K in Palette.Colors'Range loop
      ...
   end loop;

Did I missed something ?

Pascal.

--

--|------------------------------------------------------------
--| Pascal Obry                               Team-Ada Member |
--|                                                           |
--| EDF-DER-IPN-SID- T T I                                    |
--|                       Intranet: http://cln46gb            |
--| Bureau N-023            e-mail: p.obry@der.edf.fr         |
--| 1 Av G�n�ral de Gaulle  voice : +33-1-47.65.50.91         |
--| 92141 Clamart CEDEX     fax   : +33-1-47.65.50.07         |
--| FRANCE                                                    |
--|------------------------------------------------------------
--|
--|         http://perso.wanadoo.fr/pascal.obry
--|
--|   "The best way to travel is by means of imagination"







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

* Re: More C
       [not found] <vhizotrc4x7.fsf@grotte.ifi.uio.no>
                   ` (2 preceding siblings ...)
  2000-01-28  0:00 ` Gautier
@ 2000-01-30  0:00 ` Nick Roberts
       [not found]   ` <vhioga1r2j8.fsf@grotte.ifi.uio.no>
  3 siblings, 1 reply; 11+ messages in thread
From: Nick Roberts @ 2000-01-30  0:00 UTC (permalink / raw)


With the greatest respect, I think this a classic case of C programmer
trying to make Ada do things the way they have to be done in C.

In Ada, you are able to specify the representation of types, and you also
have recourse to the standard Interfaces.C package (and its children) for
interfacing to C functions and objects. This means that, in Ada, you can
often specify types that correspond more closely to the high-level meaning
of a type, and let representation clauses, as well as type derivation
techniques, take care of the nitty gritty details of how they should be
represented in the machine.

   type Light_Level_8 is range 0..255;
   for Light_Level_8'Size use 8;

   type SDL_Color is
      record
         Red, Green, Blue: Light_Level_8;
      end record;

   for SDL_Color use
      record
         Red at 0 range 0..7;
         Green at 0 range 8..15;
         Red at 0 range 16.23;
      end record;

   for SDL_Color'Size use 32;

   type SDL_Color_Array is array (Integer) of aliased SDL_Color;

   SDLCT: SDL_Color := (0,0,0); -- default 'terminator' of arrays
   -- provided because Interfaces.C.Pointers needs it, but unlikely to be
used

   package SDL_Color_Pointers is
      new Interfaces.C.Pointers(Integer,SDL_Color,SDL_Color_Array,SDLCT);

   subtype Color_Count is Interfaces.C.Int range 0..Interfaces.C.Int'Last;

   type SDL_Palette is
      record
         Number_Of_Colors: Color_Count;
         Colors: SDL_Color_Pointers.Pointer;
      end record;

   Int_Size: constant := Interfaces.C.Int'Size;

   for SDL_Palette use
      record
         Number_of_Colors at 0 range 0..Int_Size-1;
         Colors at 0 range
Int_Size..Int_Size+SDL_Color_Pointers.Pointer'Size-1;
      end record;

You can use the Value function (and others) of the SDL_Color_Pointers
package to access, easily and efficiently, the contents of arrays pointed to
by the Colors component.

Ada offers a particularly better way of accessing your display buffer.

   type Light_Level_2 is range 0..3;
   for Light_Level_2'Size use 2;

   type Light_Level_3 is range 0..7;
   for Light_Level_3'Size use 3;

   type Color_Descriptor_8 is
      record
         Red, Green: Light_Level_3;
         Blue: Light_Level_2;
      end record;

   for Color_Desriptor_8 use
      record
         Red: at 0 range 0..2;
         Green: at 0 range 3..5;
         Blue: at 0 range 6..7;
      end record;

   -- and so on for Color_Descriptor_16 and Color_Descriptor_32

   type Display_Buffer_8 is array (Integer, Integer) of aliased
Color_Descriptor_8;
   type Display_Buffer_16 is array (Integer, Integer) of aliased
Color_Descriptor_16;
   type Display_Buffer_32 is array (Integer, Integer) of aliased
Color_Descriptor_32;

   pragma Convention(Fortran,Display_Buffer_8);
   pragma Convention(Fortran,Display_Buffer_16);
   pragma Convention(Fortran,Display_Buffer_32);
   -- for (X,Y) ensure X dimension varies faster than Y

   package Display_Buffer_8_Pointers is
      new
Interfaces.C.Pointers(Integer,Color_Descriptor_8,Display_Buffer_8,...);
   -- etc

   subtype CGA_Buffer is Display_Buffer_8(1..320,1..200);
   for CGA_Buffer'Size use 320*200*8;
   pragma Volatile(CGA_Buffer); -- tell Ada it's memory mapped

   type CGA_Buffer_Access is access all CGA_Buffer;

You might import 'data', using the Import pragma, use Unchecked_Conversion
to typecast it as a Display_Buffer_8/16/32_Pointers.Pointer, and then
convert from Display_Buffer_8/16/32_Pointers.Pointer to CGA_Buffer_Access
(for example). Now you can read from and write into the buffer just like you
would a normal two-dimensional Ada array. You can't really get much more
convenient than that.

NB: the two-dimensional array addressing should be optimised adequately by
most Ada compilers, but if not, and you need the extra speed, you can use
the Value function (and others) to access the contents of the display
buffers instead. In cases such as this, try to 'wrap up' higher level
operations into procedures and functions; the Inline pragma can be used to
prevent this technique from reducing speed.

Best of luck!

--
Nick Roberts
http://www.adapower.com/lab/adaos







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

* Re: More C
       [not found]   ` <vhioga1r2j8.fsf@grotte.ifi.uio.no>
@ 2000-02-01  0:00     ` tmoran
  2000-02-02  0:00     ` Nick Roberts
  2000-02-03  0:00     ` Keith Thompson
  2 siblings, 0 replies; 11+ messages in thread
From: tmoran @ 2000-02-01  0:00 UTC (permalink / raw)


>What if the compiler decides to optimize access to the record,
>so the real memory structure becomes as follows?
  If you give a record representation clause it can't.  Without
the rep' clause, yes, and there are compilers that would optimize
by putting things at double word boundaries or whatever.  That's
the whole reason for rep clauses - when the memory layout really,
truly, has to be a certain way.

>it's not going to replace the original one dimentional buffer, since
>you then would have to know the dimentions, or at least a set of possible
>dimentions, in advance.  But you could as example read the dimentions
>from the command line or from an image file.
  A long time ago I made a VESA graphic interface.  At initialization
it asked the hardware what resolution modes were available, found
the best (criterion supplied by the application program), and defined
  subtype X_Range is Integer range 0 .. X_Res;
  subtype Y_Range is Integer range 0 .. Y_Res;
which could then be used for
  Image : array(Y_Range, X_Range) of Pixels;
It's certainly no less efficient to have the compiler generate
code to multiply the Y coordinate by the row size and add the
X coordinate, vs having the user do it explicitly and visibly.
It may even be more efficient.  It's also a lot less likely to
have a mistake.




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

* Re: More C
       [not found]   ` <vhioga1r2j8.fsf@grotte.ifi.uio.no>
  2000-02-01  0:00     ` tmoran
@ 2000-02-02  0:00     ` Nick Roberts
  2000-02-03  0:00     ` Keith Thompson
  2 siblings, 0 replies; 11+ messages in thread
From: Nick Roberts @ 2000-02-02  0:00 UTC (permalink / raw)


Jan's comments broadly accepted.

It surely demonstrates one aspect of the deficiencies of C as a software
engineering language, that the programmer has, in general, no control over
how types are represented, and that it is common for C compilers to vary
from one another (and the ANSI standard) in this matter.

In this respect, it is necessary to think of interfacing Ada source code not
to C source code, but to C object code (i.e. C source as compiled by a
particular version of a particular compiler, with a particular set of flags
in force).

To the rescue, to a certain extent, comes the ability of most C compilers to
output an assembly listing (or other listing) that shows the representations
(and addresses) chosen for types and objects.

--
Nick Roberts
http://www.adapower.com/lab/adaos

"Jan Kroken" <jankr@nntp.ifi.uio.no> wrote in message
news:vhioga1r2j8.fsf@grotte.ifi.uio.no...
> ...
> What if the [C] compiler decides to optimize access to the record,
> so the real memory structure becomes as follows?
>
> for SDL_Color use
>    record
>      Red   at 0  range 0..7;
>      Green at 32 range 32..39;
>      Blue  at 64 range 64..71;
>    end record;
> for SDL_Color'Size use 128;
> ...







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

* Re: More C
       [not found]   ` <vhioga1r2j8.fsf@grotte.ifi.uio.no>
  2000-02-01  0:00     ` tmoran
  2000-02-02  0:00     ` Nick Roberts
@ 2000-02-03  0:00     ` Keith Thompson
  2 siblings, 0 replies; 11+ messages in thread
From: Keith Thompson @ 2000-02-03  0:00 UTC (permalink / raw)


Jan Kroken <jankr@nntp.ifi.uio.no> writes:
[...]
> What if the compiler decides to optimize access to the record,
> so the real memory structure becomes as follows?
> 
> for SDL_Color use
>    record
>      Red   at 0  range 0..7;
>      Green at 32 range 32..39;
>      Blue  at 64 range 64..71;
>    end record;
> for SDL_Color'Size use 128;

You should be able to use pragma Convention(C, SDL_Color); it's then
up to the Ada compiler to lay out the record the same way the C
compiler does.

If it doesn't do this properly, you may have to resort to record
representation clauses, or perhaps to an implementation-defined
pragma.

-- 
Keith Thompson (The_Other_Keith) kst@cts.com  <http://www.ghoti.net/~kst>
San Diego Supercomputer Center           <*>  <http://www.sdsc.edu/~kst>
Welcome to the last year of the 20th century.




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

end of thread, other threads:[~2000-02-03  0:00 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <vhizotrc4x7.fsf@grotte.ifi.uio.no>
2000-01-28  0:00 ` More C tmoran
2000-01-28  0:00   ` David Starner
2000-01-28  0:00     ` Pascal Obry
2000-01-28  0:00       ` David Starner
2000-01-28  0:00         ` tmoran
2000-01-28  0:00 ` Jeff Carter
2000-01-28  0:00 ` Gautier
2000-01-30  0:00 ` Nick Roberts
     [not found]   ` <vhioga1r2j8.fsf@grotte.ifi.uio.no>
2000-02-01  0:00     ` tmoran
2000-02-02  0:00     ` Nick Roberts
2000-02-03  0:00     ` Keith Thompson

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