views:

167

answers:

8

I need to send an integer through a NetworkStream. The problem is that I only can send bytes. Thats why I need to split the integer in four byte's and send those and at the other end convert it back to a int.

For now I need this only in C#. But for the final project I will need to convert the four bytes to an int in Lua.

[EDIT] How about in Lua?

+5  A: 

Try

BitConverter.GetBytes()

http://msdn.microsoft.com/en-us/library/system.bitconverter.aspx

Just keep in mind that the order of the bytes in returned array depends on the endianness of your system.

EDIT: As for the Lua part, I don't know how to convert back. You could always multiply by 16 to get the same functionality of a bitwise shift by 4. It's not pretty and I would imagine there is some library or something that implements it. Again, the order to add the bytes in depends on the endianness, so you might want to read up on that

Maybe you can convert back in C#?

Nubsis
+1  A: 

investigate the BinaryWriter/BinaryReader classes

Gary
+1  A: 

Convert an int to a byte array and display : BitConverter ...

www.java2s.com/Tutorial/CSharp/0280__Development/Convertaninttoabytearrayanddisplay.htm

Integer to Byte - Visual Basic .NET answers

http://bytes.com/topic/visual-basic-net/answers/349731-integer-byte

How to: Convert a byte Array to an int (C# Programming Guide)

http://msdn.microsoft.com/en-us/library/bb384066.aspx

ratty
+1  A: 

As Nubsis says, BitConverter is appropriate but has no guaranteed endianness.

I have an EndianBitConverter class in MiscUtil which allows you to specify the endianness. Of course, if you only want to do this for a single data type (int) you could just write the code by hand.

BinaryWriter is another option, and this does guarantee little endianness. (Again, MiscUtil has an EndianBinaryWriter if you want other options.)

Jon Skeet
+2  A: 

BitConverter is the easiest way, but if you want to control the order of the bytes you can do bit shifting yourself.

int foo = int.MaxValue;
byte lolo = (byte)(foo & 0xff);
byte hilo = (byte)((foo >> 8) & 0xff);
byte lohi = (byte)((foo >> 16) & 0xff);
byte hihi = (byte)(foo >> 24);

Also.. the implementation of BitConverter uses unsafe and pointers, but it's short and simple.

public static unsafe byte[] GetBytes(int value)
{
   byte[] buffer = new byte[4];
   fixed (byte* numRef = buffer)
   {
      *((int*) numRef) = value;
   }
   return buffer;
}
Mikael Svenson
A: 

To convert to a byte[]:

BitConverter.GetBytes(int)

http://msdn.microsoft.com/en-us/library/system.bitconverter.aspx

To convert back to an int:

BitConverter.ToInt32(byteArray, offset)

http://msdn.microsoft.com/en-us/library/system.bitconverter.toint32.aspx

I'm not sure about Lua though.

If you are concerned about endianness use John Skeet's EndianBitConverter. I've used it and it works seamlessly.

C# supports their own implementation of htons and ntohs as:

But they only work on signed int16, int32, int64 which means you'll probably end up doing a lot of unnecessary casting to make them work, and if you're using the highest order bit for anything other than signing the integer, you're screwed. Been there, done that. ::tsk:: ::tsk:: Microsoft for not providing better endianness conversion support in .NET.

Evan Plaice
A: 

Here are some functions in Lua for converting a 32-bit two's complement number into bytes and converting four bytes into a 32-bit two's complement number. A lot more checking could/should be done to verify that the incoming parameters are valid.

-- convert a 32-bit two's complement integer into a four bytes (network order)
function int_to_bytes(n)
  if n > 2147483647 then error(n.." is too large",2) end
  if n < -2147483648 then error(n.." is too small",2) end
  -- adjust for 2's complement
  n = (n < 0) and (4294967296 + n) or n
  return (math.modf(n/16777216))%256, (math.modf(n/65536))%256, (math.modf(n/256))%256, n%256
end

-- convert bytes (network order) to a 32-bit two's complement integer
function bytes_to_int(b1, b2, b3, b4)
  if not b4 then error("need four bytes to convert to int",2) end
  local n = b1*16777216 + b2*65536 + b3*256 + b4
  n = (n > 2147483647) and (n - 4294967296) or n
  return n
end

print(int_to_bytes(256)) --> 0 0 1 0
print(int_to_bytes(-10)) --> 255 255 255 246
print(bytes_to_int(255,255,255,246)) --> -10
gwell
+1  A: 

For Lua, check out Roberto's struct library. (Roberto is one of the authors of Lua.) It is more general than needed for the specific case in question, but it isn't unlikely that the need to interchange an int is shortly followed by the need to interchange other simple types or larger structures.

Assuming native byte order is acceptable at both ends (which is likely a bad assumption, incidentally) then you can convert a number to a 4-byte integer with:

buffer = struct.pack("l", value)

and back again with:

value = struct.unpack("l", buffer)

In both cases, buffer is a Lua string containing the bytes. If you need to access the individual byte values from Lua, string.byte is your friend.

To specify the byte order of the packed data, change the format from "l" to "<l" for little-endian or ">l" for big-endian.

The struct module is implemented in C, and must be compiled to a DLL or equivalent for your platform before it can be used by Lua. That said, it is included in the Lua for Windows batteries-included installation package that is a popular way to install Lua on Windows systems.

RBerteig