배열을 포함하는 구조체를 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 message = 새 메시지 (packet, new BinaryMessageFormatter()); q.Send (message); –
간단히 말해, 디지털 및 아날로그 포인트를 많이 저장하고자하므로 가장 작은 패킷을 사용하고 싶습니다. 이 예제는 간단하게하기 위해 작습니다. –