comp.lang.ada
 help / color / mirror / Atom feed
From: Jeff Carter <spam.carter.not@spam.innocon.com>
To: Craig Allen <cpallen@nospam.com>
Subject: Re: simple question - how to emulate void * ?
Date: 1998/10/23
Date: 1998-10-23T00:00:00+00:00	[thread overview]
Message-ID: <36308AA6.86327E09@spam.innocon.com> (raw)
In-Reply-To: 9v6hGdgMLuwN-pn2-Oc41W71Dq3U9@dt182n2f.tampabay.rr.com

Craig Allen wrote:
> 
> Well, yes, I'm new to ada, and coming from C.
> 
> Now, I have some simple functionality that I'd like to see, and can't
> figure out how to do it in Ada.
> 
> in C, it goes like this:
> 
> /* libfile.c */
> 
> void print_bytes(void *buf, int len)
> {
>         int i;
>         char *c = buf;
>         for (i=0; i<len; ++i) {
>                 putchar(c[i]);
>         }
> 
>         return;
> }
> 
> /* app.c */
>         ...
>         struct any_struct data;
>         print_bytes(&data, sizeof (struct data));
>         ...
> 
> The lib can access byte for byte the data passed in regardless of the
> app's struct type.  Now, Ada being such a strongly typed language, I
> have tried different things but just can't seem to figure out how to
> get this lib routine to work on my buffer, regardless of its type.
> I've come close with some generic functions, but can't seem to get the
> syntax acceptable for the compiler.
> Can someone point me in the right direction?
> 
> Specifically, this library function will be shipping things out a
> serial port, one byte at a time, that is why i'd like to address it as
> an array of bytes.
> 
> Thanks.
> -Craig

Well, some of the responses showed how to implement this exact
capability (print anything as an array of characters) and something
along the lines of what is really desired (print anything as an array of
bytes), but the real answer should be, "You should not try to emulate
'void *' in Ada.". No one has addressed how to solve this problem
properly using Ada. Basically, the question is how to access an object
of any type as an array of bytes and apply an arbitrary operation to
that array of bytes, such as shipping the bytes out a serial port.

For shipping the bytes out a serial port, streams seem to be the best
way. Define the 'Write operation for the type(s) to write the object(s)
byte by byte.

In general, though, assume we want to apply an arbitrary operation on an
array of bytes to any type. I would specifiy this as something like

package Byte_By_Byte is
   Byte_Size : constant := 8;
   type Byte is mod 2 ** Byte_Size;
   for Byte'Size use Byte_Size;

   type Byte_List is array (Positive range <>) of Byte;
   for Byte_List'Component_Size use Byte_Size;
   pragma Pack (Byte_List);

   generic -- Apply_Operation
      type Anything (<>) is limited private;

      with procedure Operation (List : in Byte_List);
   procedure Apply_Operation (Thing : in Anything);
end Byte_By_Byte;

The user of this would then define the operation on a list of bytes:

with Ada.Text_Io;
with Byte_By_Byte;
...
   procedure Write_As_Characters (List : in Byte_By_Byte.Byte_List) is
   begin -- Write_As_Characters
      All_Bytes : for I in List'range loop
         Ada.Text_Io.Put (Item => Character'Val (List (I) ) );
      end loop All_Bytes;
   end Write_As_Characters;

(or any other operation the user chooses, such as sending the bytes to a
serial port), define the type(s):

   type Ugly is record
      X : Integer  := Integer'First;
      Y : Float    := 0.0;
      Z : Duration := Duration'Last;
   end record;

instantiate the generic:

   procedure Write_Bytes is new Byte_By_Byte.Apply_Operation
      (Anything => Ugly, Operation => Write_As_Characters);

and use it:

   U : Ugly := (X => Integer'Last, Y => 0.0, Z => Duration'First);
begin
   Write_Bytes (Thing => U);

Then Allen's question would be, how should he implement the body of
Byte_By_Byte. The responses I've seen should give him a clue. I'd
suggest something like

package body Byte_By_Byte is
   procedure Apply_Operation (Thing : in Anything) is
      List : Byte_List (1 .. (Thing'Size + Byte_Size - 1) / Byte_Size);
      for List'Address use Thing'Address;
   begin -- Apply_Operation
      Operation (List => List);
   end Apply_Operation;
end Byte_By_Byte;

I have not compiled any of this code, and apologize in advance for the
errors I have made. (I take it as given that I have made errors; that's
why I have inspections of anything I do related to SW development.
However, here I have not even let a compiler find the most blatant of my
errors, so my certainty that I've made errors is stronger.)

I think this is a better answer because it shows how Ada features are
intended to be used, within limits and dealing with something of
interest to the questioner. The short answers will likely result Allen
going away and solving this problem, but by writing Ada-C.

-- 
Jeff Carter  PGP:1024/440FBE21
"We burst our pimples at you."
Monty Python & the Holy Grail




  parent reply	other threads:[~1998-10-23  0:00 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
1998-10-23  0:00 simple question - how to emulate void * ? Craig Allen
1998-10-23  0:00 ` Tom Moran
1998-10-23  0:00 ` Dale Stanbrough
1998-10-22  0:00   ` Hans Marqvardsen
1998-10-23  0:00     ` John McCabe
1998-10-23  0:00       ` Ed Falis
1998-10-23  0:00         ` dennison
1998-10-24  0:00           ` Joe Wisniewski
1998-10-25  0:00           ` dewar
1998-10-24  0:00         ` Dale Stanbrough
1998-10-24  0:00           ` Robert A Duff
1998-10-24  0:00           ` Tucker Taft
1998-10-23  0:00       ` dennison
1998-10-22  0:00   ` Hans Marqvardsen
1998-10-23  0:00   ` David C. Hoos, Sr.
1998-10-23  0:00   ` David C. Hoos, Sr.
1998-10-23  0:00 ` Jeff Carter [this message]
1998-10-24  0:00   ` Dale Stanbrough
1998-10-25  0:00     ` dewar
1998-11-05  0:00 ` Craig Allen
1998-11-06  0:00   ` Dale Stanbrough
1998-11-06  0:00     ` Matthew Heaney
1998-11-06  0:00       ` dewarr
1998-11-06  0:00   ` Tom Moran
replies disabled

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