Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

conversion to byte[]

Status
Not open for further replies.

stonee74

Technical User
Nov 12, 2001
49
0
0
CH

hello again,

I'm really getting crazy on this:

I have an object, derived from another class containing some enums. I need to send this object down to a server via a socket.
My problem is, that in c# this socket.send() method does not accept ref or pointers but by byte[].
I'm trying now since hours to create a byte[] from my object. Is this possible somehow?



code:--------------------------------------------------------------------------------
m_socket.Send((byte[]) PacketStart,0,(int)PacketSize,0);
--------------------------------------------------------------------------------


this gives me a 'System.InvalidCastException', the type comes into this method as 'ref object PacketStart'....

thanks a lot, I hope somebody can help me out!

regards,
stonee
 
This code snippet from MSDN shows how to send a string over a socket:
Code:
byte[] msg = Encoding.ASCII.GetBytes("This is a test");

// Blocks until send returns.
int i = s.Send(msg, 0, msg.Length, SocketFlags.None);
So all you have to do is figure out a way to serialize your object into a string. Which the ToString method (which every object inherits from the Object class) does. You'll just have to override the default implementation (since it probably doesn't do what you want), and call it like this:
Code:
byte[] msg = Encoding.ASCII.GetBytes(PacketStart.ToString());

// Blocks until send returns.
int i = s.Send(msg, 0, msg.Length, SocketFlags.None);

Chip H.
 
Chip H.,

Thanks a lot for your help.
There's one thing i have not mentioned in the post before, this app should run on the .NET Compact Framework, where, among others, serializing is not possible within the available system classes. Do you think there is a possibility I could do it anyway, or may there be another different approach?

thanks again,
stonee
 
Sorry, I haven't worked with the Compact Framework, so I can't help you there.

But I would suggest you write your own ToString method, in which you take the instance data in your class and append it up into a String.

Chip H.
 
and another thing, my object is a class of structs and enums, not a string. I need to take out the binary data from memory (kinda pointer)and send that to the server.... but how?
 
Please re-read my second sentence.

You must build up your own string using the various Convert methods in order to serialize >out<, and then reverse the process to serialize >in< at the other end of your socket connection.

XML is a good candidate for containing your classes instance data, so you won't have any problems determining where one string value ends and another one begins.

Chip H.
 
serializing is not possible within the available system classes of .NET CF. I guess i need to operate with unsafe code, what do u think?

First I wanted to use wrapping instead of rewriting the code, Did u made some experiences already with this?
please find attached post

Thanks a lot again,
stonee

--------------------------------------------------------
I need to use an existing Programming Interface which is available whether as a 'COM object dll' or' 2 C++ header files' under .NET.
I used the COM object, this works quite nice inVB.NET as well in C#, using the System.Runtime.InteropServices.TypeLibConverter class.
In fact everything will be done automatically and i can use my Interface like in the unmanaged world, great!

The main problem is will develop an application on a PocketPC, under the .NET Compact Framwork.
Since this System.Runtime.InteropServices.TypeLibConverter class does not exist under the NET CF, i need to use the C++ interface, but this gives me headache.

So far I found out the following:

To use (unmanaged) C++ Code in the managed world of .NET, there are several possibilities.
You can use the built-in .NET runtime interop facilities to talk directly to the existing code.
You can wrap the code using the managed extensions to C++.
You can rewrite the code in a .NET language.
I wanted to go in direction step 3, but I'm no longer sure what makes really sense on this one....

My interface is consisting of 3 header files. 2 of them are simply describing enumerations and structs.
The third one consists of helper classes in C++ which are easing the use of this interface a lot.


I assume that when I would go the wrapping way, that I would only need to wrap the classes I directly touch from my App in c#?
If yes then I woud need to wrap only 2 classes:

But how would I do that best? Could somebody give me an idea how to do that?


Thanks a lot,

stonee




Attached the sample classes:


//sender.h

Class1 to wrap:
// Macro to compact duplicate code

#define DATA_PACKET &Data.DataPacket, sizeof(Data.DataPacket)

class Command

{

public:

CESAPICommand() {TRACE(_T(&quot;CESAPICommand()\n&quot;));}


virtual bool SendPacket(void* PacketStart, long PacketSize)

{

TRACE(_T(&quot;Virtual SendPacket() called!\n&quot;));


return false;

};


// Send commands

bool inline Init() {CInit Data; return SendPacket(DATA_PACKET);}




bool inline SetBox(double dX1, double dY1, double dZ1, double dX2, double dY2, double dZ2)

{CSetBox Data(dX1, dY1, dZ1, dX2, dY2, dZ2); return SendPacket(DATA_PACKET);}


};



Class2 to wrap:

///Receiver.h

class Receive

{

public:

Receive() {TRACE(_T(&quot;Receive()\n&quot;));}

protected:



bool ReceiveData(void* packetStart, long packetSize)

{


if (packetStart && packetSize > 0)

return ProcessData(packetStart, packetSize);

else

return false;

};

protected:

virtual void OnInitializeAnswer() {TRACE(_T(&quot;virtual OnInitializeAnswer() call\n&quot;));}

virtual void OnGetBoxAnswer(const BoxRegionDataT& boxRegionData) {TRACE(_T(&quot;virtual OnGetBoxRegionParamsAnswer() call\n&quot;));}



protected:

// It is supposed that one and only one and COMPLETE data

// packet is being passed to this function.

// Parameter 'lBytes' just passed for diagnostics purpose

//

virtual bool ProcessData(void *pDataArrived, long lBytes)

{



PacketHeaderT *pData = (PacketHeaderT*)pDataArrived;

// Diagnostics and overflow prevention.

if (pData->lPacketSize != lBytes)

{

TRACE2(&quot;PacketSize (%ld) differs from TotalBytes (%ld) !\n&quot;, pData->lPacketSize, lBytes);

return false; // causes to signal a data receive error

} // if

switch (pData->type)

{

case ES_DT_Command: // A 'command- type' answer has arrived

{

// call general virtual function for commands

//



OnCommandAnswer(*(BasicCommandRT *)pData); // uses reference parameter. see comment in header file

// decode type of command

BasicCommandRT *pData2 = (BasicCommandRT *)pData;

// handle error

if (pData2->status != ES_RS_AllOK)

return true; // Exit here, but make sure pData2->status gets forwared somehow.

// This is done on using the general OnCommandAnswer() function above.


switch (pData2->command)

{

case ES_C_ExitApplication:

OnExitApplicationAnswer();

break;


case ES_C_GetSystemStatus:

OnGetSystemStatusAnswer(((GetSystemStatusRT*)pDataArrived)->lastResultStatus,

((GetSystemStatusRT*)pDataArrived)->trackerProcessorStatus,

((GetSystemStatusRT*)pDataArrived)->laserStatus,

((GetSystemStatusRT*)pDataArrived)->admStatus,

((GetSystemStatusRT*)pDataArrived)->esVersionNumber,

((GetSystemStatusRT*)pDataArrived)->weatherMonitorStatus,

((GetSystemStatusRT*)pDataArrived)->lFlagsValue,

((GetSystemStatusRT*)pDataArrived)->lTrackerSerialNumber);

break;





case Init

OnInitializeAnswer();

break;



case ES_C_GetReflectors:

OnGetReflectorsAnswer(((GetReflectorsRT*)pDataArrived)->iTotalReflectors,

((GetReflectorsRT*)pDataArrived)->iInternalReflectorId,

((GetReflectorsRT*)pDataArrived)->targetType,

((GetReflectorsRT*)pDataArrived)->dSurfaceOffset,

((GetReflectorsRT*)pDataArrived)->cReflectorName);

break;


// Do not treat unknown packets as error - just ignore them

TRACE(_T(&quot;Unexpected data received (ignored)\n&quot;));

break;

} // switch

return true;

} // ProcessData()

};

 
The structure of what you want to do would be very similar in C#, but the details would be very different.

I would define classes for your Header, your SystemStatus, and your Reflectors data types. I would also define an enum for your packet type.

In each class, I would define a property to be used for serialization:
Code:
class Header
{
   private int m_PacketSize;
   private PacketType m_PacketType;  // enum type

   //
   // put constructor here
   //

   // PacketSize property
   public int PacketSize {
      get
      {
         return m_PacketSize;
      }
      set
      {
         m_PacketSize = value;
      }
   }

   // PacketType property
   public PacketType PacketType {
      get
      {
         return m_PacketType;
      }
      set
      {
         m_PacketType = value;
      }
   }

   // MySerialize property
   public string MySerialize {
      get
      {
         StringBuilder sBuffer = &quot;&quot;;
         sBuffer.Append(m_PacketSize.ToString());
         sBuffer.Append(&quot;|&quot;);
         sBuffer.Append(m_PacketType.ToString());
         return sBuffer.ToString();
      }
      set
      {
         int PipePos = value.IndexOf(&quot;|&quot;);
         m_PacketSize = Convert.ToIn32(value.Substring(0, PipePos - 1));
         m_PacketType = PacketType.Parse(m_PacketType.GetType, value.Substring(PipePos + 1);
      }
   }
}

After reading from your socket, you would assign the output of your Encoding.ASCII method call to the MySerialize property. Before sending over the socket, you would read from the MySerialize property, and then send that through the Encoding.ASCII method.

My code above is from memory, so you likely will need to reference the .NET documentation to get it correct.

Chip H.
 
chiph,

I tried what you were suggesting, receive a string with value &quot;12|7|0&quot;, exactly what I assumed.
size, enum1, enum2.
But then the conversion part is not ok, I do not want to have the ascii representation of each digit. I want to have the description of that value in memory.
like:

byte[0] 12 bytes size:00001100b (12d)

byte[1] enum1 :00000000
byte[2] enum1 :00000000
byte[3] enum1 :00000000
byte[4] enum1 :00000000

byte[5] enum2 :00000000
byte[6] enum2 :00000000
byte[7] enum2 :00000000
byte[8] enum2 :00000111 (07d)

byte[9] :00000000
byte[10] :00000000
byte[11] :00000000
byte[12] :00000000

This is the way it should work...
Do ya think this is possible somehow?
In a further step i would like to pass doubles that way also...

thanks again,
stonee
 
I guess I'll need to go that way:

myclass Data = new myclass(dVal1,dVal2,dVal2);

byte[] myByte1 = System.BitConverter.GetBytes((System.Byte)Data.DataPacket.packetInfo.packetHeader.lPacketSize);
byte[] myByte2 = System.BitConverter.GetBytes((Int32)Data.DataPacket.packetInfo.packetHeader.type);
byte[] myByte3 = System.BitConverter.GetBytes((Int32)Data.DataPacket.packetInfo.command);
byte[] myByte4 = System.BitConverter.GetBytes(dVal1);
byte[] myByte5 = System.BitConverter.GetBytes(dVal2);
byte[] myByte6 = System.BitConverter.GetBytes(dVal3);
byte[] myByteOK = new byte
[Data.DataPacket.packetInfo.packetHeader.lPacketSize];
Array.Copy(myByte1,0,myByteOK,0,1);
Array.Copy(myByte2,0,myByteOK,4,1);
Array.Copy(myByte3,0,myByteOK,8,1);
Array.Copy(myByte4,0,myByteOK,12,8);
Array.Copy(myByte5,0,myByteOK,12+8,8);
Array.Copy(myByte6,0,myByteOK,12+8+8,8);

works, but maybe 2 much overhead, and not that nice? thanks for any comments..

regards,
stonee
 
OK, it sounds like what you're doing will work. Just make sure you're talking to an Intel machine at the other end of your socket, because the byte order is different from other CPU architectures.

Chip H.
 
It's an Intel, thanks for your help and comments.
I appreciated that a lot!

regards,
stonee
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top