Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Using GNAT.Sockets with Streams and Byte Swapping

98 views
Skip to first unread message

markp

unread,
May 25, 2005, 5:48:06 AM5/25/05
to
I am having a problem using GNAT.socket with streams. I can create a
stream easily and send data as follows:

Msg_Type'Write(
My_Stream_Access,
Msg);

This will work fine of both machines are the same "endian". However, if
I need to swap bytes on the variable Msg before I send, I get garbled
data on the other end.

Is there a problem with swapping bytes before the call to 'Write?

Thanks

Simon Wright

unread,
May 26, 2005, 2:00:08 AM5/26/05
to
"markp" <markw...@yahoo.com> writes:

Not as far as I know. Though it's a much better idea to swap bytes
_in_ 'Write (and 'Read).

You can write your own 'Read, 'Write attribute subprograms.

Or, you can rebuild the runtime on both sides using an XDR version of
System.Stream_Attributes (s-stratt.adb).

In recent (supported) GNATs and in GCC 3.4, 4.0 this has been supplied
in s-strxdr.adb (so copy s-strxdr.adb to s-stratt.adb and rebuild --
see Makefile.adalib in your .../adalib directory under the GCC
runtime, though Some Assembly Will [probably] Be Required).

If you are on a PowerPC the only difference between doing this and
doing nothing on the PPC (running natively big-endian -- who does
otherwise?) is that natively Wide_Character is 2 bytes, while the XDR
form is 4 bytes.

There is a problem with s-strxdr.adb, it raises the wrong exception
(an internal Data_Error rather than the standed End_Error, ISTR).

What we ended up doing was using the native PPC s-stratt.adb and
writing our own on the x86 side to match what the PPC was doing
(easier to argue the acceptability of a vendor-supplied runtime, and
our delivery platform is the PPC!)

markp

unread,
May 26, 2005, 5:28:31 AM5/26/05
to
Thanks for your reply. I have one question. In order to write my own
'Write and 'Read subprograms, would I have to change GNAT.Sockets and
rebuild the runtime? Or, is there an easier way?

Thanks again.

Alex R. Mosteo

unread,
May 26, 2005, 5:50:41 AM5/26/05
to

No, no :) You just write a conformant procedure and then:

for Your_Type'Write use <your procedure>;

Duncan Sands

unread,
May 26, 2005, 6:01:47 AM5/26/05
to markp, comp.l...@ada-france.org

The usual answer is that you should write your own 'Read and 'Write
routines. However recent versions of GNAT support the machine
independent XDR representation, which may be what you want. The
GNAT reference manual says:

13.13.2(17): Stream Oriented Attributes

If a stream element is the same size as a storage element, then the normal in-memory representation should be used by Read and Write for
scalar objects. Otherwise, Read and Write should use the smallest number of stream elements needed to represent all values in the base range
of the scalar type.

Followed. By default, GNAT uses the interpretation suggested by AI-195, which specifies using the size of the first subtype. However, such an
implementation is based on direct binary representations and is therefore target- and endianness-dependent. To address this issue, GNAT also
supplies an alternate implementation of the stream attributes Read and Write, which uses the target-independent XDR standard representation
for scalar types. The XDR implementation is provided as an alternative body of the System.Stream_Attributes package, in the file
`s-strxdr.adb' in the GNAT library. There is no `s-strxdr.ads' file. In order to install the XDR implementation, do the following:
1. Replace the default implementation of the System.Stream_Attributes package with the XDR implementation. For example on a Unix platform
issue the commands:


$ mv s-stratt.adb s-strold.adb
$ mv s-strxdr.adb s-stratt.adb

2. Rebuild the GNAT run-time library as documented in the GNAT User's Guide


markp

unread,
May 26, 2005, 7:35:18 AM5/26/05
to
We found the answer to our problem. We have types such as

type x is range 1..5;

We then make records including these types. In the rep specs, we define
them to be 32 bits. Apparently, GNAT ignores the rep spec when doing
the 'Write, so we are not sending the correct number of bits. The fix
is:

type x is range 1..5;
for x'size use 32;

This fixes our problem.

Thanks very much for your help.

Pascal Obry

unread,
May 26, 2005, 2:51:31 PM5/26/05
to

"markp" <markw...@yahoo.com> writes:

> We found the answer to our problem. We have types such as
>
> type x is range 1..5;
>
> We then make records including these types. In the rep specs, we define
> them to be 32 bits. Apparently, GNAT ignores the rep spec when doing
> the 'Write, so we are not sending the correct number of bits. The fix
> is:

This can be solved with the new Ada 2006 Stream_Size attribute.

http://www.adaic.com/standards/rm-amend/html/RM-13-13-2.html

Pascal.


--

--|------------------------------------------------------
--| Pascal Obry Team-Ada Member
--| 45, rue Gabriel Peri - 78114 Magny Les Hameaux FRANCE
--|------------------------------------------------------
--| http://www.obry.net
--| "The best way to travel is by means of imagination"
--|
--| gpg --keyserver wwwkeys.pgp.net --recv-key C1082595

Simon Wright

unread,
May 26, 2005, 4:29:12 PM5/26/05
to
"markp" <markw...@yahoo.com> writes:

> We found the answer to our problem. We have types such as
>
> type x is range 1..5;
>
> We then make records including these types. In the rep specs, we define
> them to be 32 bits. Apparently, GNAT ignores the rep spec when doing
> the 'Write, so we are not sending the correct number of bits. The fix

The rep spec is about layout in memory, not on the stream.

> is:
>
> type x is range 1..5;
> for x'size use 32;
>
> This fixes our problem.
>
> Thanks very much for your help.

You're welcome (and I'm glad it didn't turn out to be so difficult
after all!)

Florian Weimer

unread,
May 26, 2005, 5:02:00 PM5/26/05
to
* Simon Wright:

> You're welcome (and I'm glad it didn't turn out to be so difficult
> after all!)

Mark is not using an Ada 95 compiler, it seems. It used to be more
difficult because the size of the base type determined the number of
stream elements used, and the representation clause doesn't change it.

Vinzent 'Gadget' Hoefler

unread,
May 27, 2005, 2:38:29 AM5/27/05
to
Florian Weimer wrote:

> Mark is not using an Ada 95 compiler, it seems. It used to be more
> difficult because the size of the base type determined the number of
> stream elements used, and the representation clause doesn't change it.

Read again. He _changed_ the size of the base type. (Universal_Integer
doesn't have a fixed size, does it?)


Vinzent.

--
worst case: The wrong assumption there actually is one.

0 new messages