From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=0.1 required=5.0 tests=AC_FROM_MANY_DOTS,BAYES_00, INVALID_MSGID autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,af247e41be5f18ab X-Google-Attributes: gid103376,public From: Jeff Carter Subject: Re: simple question - how to emulate void * ? Date: 1998/10/23 Message-ID: <36308AA6.86327E09@spam.innocon.com>#1/1 X-Deja-AN: 404291120 Content-Transfer-Encoding: 7bit References: <9v6hGdgMLuwN-pn2-Oc41W71Dq3U9@dt182n2f.tampabay.rr.com> To: Craig Allen Content-Type: text/plain; charset=us-ascii Organization: Innovative Concepts, Inc. Mime-Version: 1.0 Newsgroups: comp.lang.ada Date: 1998-10-23T00:00:00+00:00 List-Id: 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 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