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=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Thread: 103376,57b537327d52e653 X-Google-Attributes: gid103376,public,usenet X-Google-Language: ENGLISH,ASCII-7-bit Path: g2news2.google.com!news2.google.com!border1.nntp.dca.giganews.com!nntp.giganews.com!wns13feed!worldnet.att.net!attbi_s21.POSTED!53ab2750!not-for-mail From: "Jeffrey R. Carter" User-Agent: Thunderbird 1.5.0.12 (Windows/20070509) MIME-Version: 1.0 Newsgroups: comp.lang.ada Subject: Re: Byte streams References: <1186082475.711489.104420@e9g2000prf.googlegroups.com> In-Reply-To: <1186082475.711489.104420@e9g2000prf.googlegroups.com> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Message-ID: NNTP-Posting-Host: 12.201.97.213 X-Complaints-To: abuse@mchsi.com X-Trace: attbi_s21 1186119242 12.201.97.213 (Fri, 03 Aug 2007 05:34:02 GMT) NNTP-Posting-Date: Fri, 03 Aug 2007 05:34:02 GMT Organization: AT&T ASP.att.net Date: Fri, 03 Aug 2007 05:34:02 GMT Xref: g2news2.google.com comp.lang.ada:1345 Date: 2007-08-03T05:34:02+00:00 List-Id: shaunpatterson@gmail.com wrote: > > I've written a socket functions to send and receive data in C and then > created a spec in Ada so I could use those same functions: > > -- C functions -- > > unsigned char *readBytes (const unsigned int numBytes); > void sendBytes (unsigned char *data, const unsigned int numBytes); > > > --- Ada side > type Byte is mod 256; > for Byte'Size use 8; > > type ByteStream is array (Integer range <>) of Byte; > > > function readBytes (numBytes : Integer) return System.Address; > pragma import (C, readBytes, "readBytes"); Integer? What would Readbytes (-7) mean? > procedure sendBytes (data : ByteStream; numBytes : Integer); > pragma import (C, sendBytes, "sendBytes"); For a direct translation, you should use the types in Interfaces.C and Interfaces.C.Strings (ARM B.3[.1]): function Read_Bytes (Num_Bytes : in Interfaces.C.Unsigned) return Interfaces.C.Strings.Chars_Ptr; procedure Send_Bytes (Data : in Interfaces.C.Char_Array; Num_Bytes : in Interfaces.C.Unsigned); More in the spirit rather than the letter of what the C is trying to say, you probably want to use System.Storage_Elements.Storage_Array: procedure Send_Bytes (Data : in System.Storage_Elements.Storage_Array; Num_Bytes : in Interfaces.C.Unsigned); You send data by creating a subtype of System.Storage_Elements.Storage_Array with a length equal to the value you'll pass to Num_Bytes, and instantiating Ada.Unchecked_Conversion with this subtype as the target. > type IntegerPtr is access all Integer; > function to_IntegerPtr is new Unchecked_Conversion > (source => System.Address, target => > IntegerPtr); > > --- this works...and I can do all the conversions I need using an > unchecked_conversion This is highly compiler dependent. There is no guarantee that a System.Address and a C pointer are the same size, much less the same representation. There is no guarantee that a System.Address and an access value are the same size, much less the same representation. There are compilers where these things aren't and this won't work. For situations where you must convert between System.Address and access values, there's System.Address_To_Access_Conversions, but this isn't one of those cases. Reading is a little more complicated: with System; type Value is ... type Value_Ptr is access all Value; pragma Convention (C, Value_Ptr); The pragma Convention is important; it tells the compiler to use the same representation as C. That may be different from Ada's default representation. function Get (Num_Bytes : in Interfaces.C.Unsigned := Value'Size / System.Storage_Unit) return Value_Ptr; This is a way to do it at the low level (streams are another, and perhaps better, way). But Ada is usually about hiding the low level. You shouldn't want your application declaring access types and imported functions and doing unchecked conversions all over the place. generic -- Socket_IF type Value (<>) is private; package Socket_IF is procedure Send (Data : in Value); function Read return Value; end Socket_IF; with Ada.Unchecked_Conversion; with Interfaces.C; with System.Storage_Elements; package Body Socket_IF is subtype Unsigned is Interfaces.C.Unsigned; use type Unsigned; Num_Bytes : constant Unsigned := Value'Size / System.Storage_Unit; procedure Send (Data : in Value) is subtype List is System.Storage_Elements.Storage_Array (1 .. Num_Bytes); function To_List is new Ada.Unchecked_Conversion (Source => Value, Target => List); procedure C_Send (Data : in List; Size : in Unsigned); pragma Import (C, C_Send, ...); begin -- Send C_Send (Data => To_List (Data), Size => Num_Bytes); end Send; function Read return Value is type Value_Ptr is access all Value; pragma Convention (C, Value_Ptr); function C_Read (Size : in Unsigned) return Value_Ptr; pragma Import (C, C_Read, ...); begin -- Read return C_Read (Num_Bytes).all; end Read; end Socket_IF; I haven't tested this, but it might even work. Now your application only has to instantiate Socket_IF for each type of interest, and call the resulting Send and Read operations. Much replication of code is eliminated, and you only have to get this right once. Something similar for the streams approach is left as an exercise for the reader. -- Jeff Carter "We call your door-opening request a silly thing." Monty Python & the Holy Grail 17