配列を含む構造体をC#のバイト配列に変換するにはどうすればよいですか?配列を含む構造体をバイト配列に変換する方法は?
配列なしの構造体に関する質問がありました。here
しかし、構造体は、このような配列が含まれている場合:
public struct DiObject
{
public byte Command;
public byte ErrorClass;
public byte Reserved;
public byte Flags;
}
public struct MyPacket
{
public uint ProtocolIdentifier;
public uint NumDi;
public DiObject[] Di;
}
をバイトで構造体を変換するときに、アクセス違反の例外を除いて結果:
private static byte[] GetBytes(MyPacket packet, int packetSize)
{
var data = new byte[packetSize];
var ptr = Marshal.AllocHGlobal(packetSize);
// ==== Access violation exception occurs here ====
Marshal.StructureToPtr(packet, ptr, true);
Marshal.Copy(ptr, data, 0, packetSize);
Marshal.FreeHGlobal(ptr);
return data;
}
私の目標は、メッセージを送信することですMSMQを使用するメッセージキュー内のバイト数。
ここでは、問題をコンパイルして再現する完全なコードです。
using System;
//using System.IO;
//using System.Messaging;
using System.Runtime.InteropServices;
namespace StructToBytes
{
// 4 bytes
[Serializable]
public struct DiObject
{
public byte Command;
public byte ErrorClass;
public byte Reserved;
public byte Flags;
}
// 8 + (numDi*4) bytes
[Serializable]
public struct MyPacket
{
public uint ProtocolIdentifier;
public uint NumDi;
public DiObject[] Di;
}
internal class Program
{
private static byte[] GetBytes(MyPacket packet, int packetSize)
{
var data = new byte[packetSize];
var ptr = Marshal.AllocHGlobal(packetSize);
// ==== Access violation exception occurs here ====
Marshal.StructureToPtr(packet, ptr, true);
Marshal.Copy(ptr, data, 0, packetSize);
Marshal.FreeHGlobal(ptr);
return data;
}
private static MyPacket FromBytes(byte[] data)
{
var packet = new MyPacket();
var dataSize = Marshal.SizeOf(packet);
var ptr = Marshal.AllocHGlobal(dataSize);
Marshal.Copy(data, 0, ptr, dataSize);
packet = (MyPacket) Marshal.PtrToStructure(ptr, packet.GetType());
Marshal.FreeHGlobal(ptr);
return packet;
}
private static void Main(string[] args)
{
const string queuePath = @".\private$\test_msmq";
// Create the packet
var packet = new MyPacket();
// 8 bytes
packet.ProtocolIdentifier = 1;
packet.NumDi = 2;
// 8 bytes
packet.Di = new DiObject[packet.NumDi];
packet.Di[0].Command = 2;
packet.Di[0].ErrorClass = 3;
packet.Di[0].Flags = 4;
packet.Di[0].Reserved = 5;
packet.Di[1].Command = 6;
packet.Di[1].ErrorClass = 7;
packet.Di[1].Flags = 8;
packet.Di[1].Reserved = 9;
// Convert the struct in bytes
const int packetSize = 16;
var packetBytes = GetBytes(packet, packetSize);
// Create the message
/*
var msg = new Message();
msg.BodyStream = new MemoryStream(packetBytes);
// Open or create the message queue
if (!MessageQueue.Exists(queuePath))
MessageQueue.Create(queuePath);
// Open the queue
var q = new MessageQueue(queuePath); // {Formatter = new BinaryMessageFormatter()};
// Send the message to the queue
q.Send(msg);
*/
}
}
}
「BinaryMessageFormatter」はこれをシリアル化してみませんか?メッセージを小さくしようとしているのでしょうか? MSMQメッセージのオーバーヘッドは、すでにメッセージの内容自体よりも大きくなるため、このような小さなものでは、大きな違いはありません。 –
BinaryMessageFormatterを使用すると、データは16バイトではなく340バイトとして保存されます。私は可能な限り小さなパケットを望みます。ここにこれを示すコード://メッセージキューを開くか作成する if(!MessageQueue.Exists(queuePath)) MessageQueue.Create(queuePath); //キューを開く var q =新しいMessageQueue(queuePath); // {Formatter = new BinaryMessageFormatter()}; varメッセージ=新しいメッセージ(パケット、新しいBinaryMessageFormatter()); q.Send(メッセージ); –
要するに、私はデジタルとアナログの多くの点を保存したいので、最小限のパケットを可能にしたいと思います。この例は単純であるために小さいです。 –