독서는 C/C++데이터 구조에서는 C#에서 바이트 배열
-
08-06-2019 - |
문제
무엇을 할 수있는 가장 좋은 방법이 될 것이를 채우기 위 C#구조체에서 byte[]배열 데이터에서는 C/C++구?C 구조는 다음과 같이 보일 것이다(내 C 은 매우 녹슨):
typedef OldStuff {
CHAR Name[8];
UInt32 User;
CHAR Location[8];
UInt32 TimeStamp;
UInt32 Sequence;
CHAR Tracking[16];
CHAR Filler[12];
}
및 채울 것인지 무언가가 다음과 같다:
[StructLayout(LayoutKind.Explicit, Size = 56, Pack = 1)]
public struct NewStuff
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
[FieldOffset(0)]
public string Name;
[MarshalAs(UnmanagedType.U4)]
[FieldOffset(8)]
public uint User;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
[FieldOffset(12)]
public string Location;
[MarshalAs(UnmanagedType.U4)]
[FieldOffset(20)]
public uint TimeStamp;
[MarshalAs(UnmanagedType.U4)]
[FieldOffset(24)]
public uint Sequence;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
[FieldOffset(28)]
public string Tracking;
}
가장 좋은 방법은 무엇입을 복사 OldStuff
하기 NewStuff
, 는 경우 OldStuff
이 전달되었으로 byte[]배열?
나는 현재 다음과 같이지만,그것은 듯한 느낌을 주는 바랍니다.
GCHandle handle;
NewStuff MyStuff;
int BufferSize = Marshal.SizeOf(typeof(NewStuff));
byte[] buff = new byte[BufferSize];
Array.Copy(SomeByteArray, 0, buff, 0, BufferSize);
handle = GCHandle.Alloc(buff, GCHandleType.Pinned);
MyStuff = (NewStuff)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(NewStuff));
handle.Free();
은 거기에 더 나은 방식으로 이러한 작업을 수행하는?
를 사용하는 것에 BinaryReader
클래스 제공의 성능 향상을 위해 고정하고 메모리를 사용하여 Marshal.PtrStructure
?
해결책
내가 무엇을 볼 수 있습니다 그런 맥락에서,당신은 당신이 필요하지 않을 복사 SomeByteArray
으로 버퍼입니다.당신은 단순히 당신을 얻을 필요가에서 핸들 SomeByteArray
,핀,복사 IntPtr
를 사용하여 데이터 PtrToStructure
다음 마우스 단추를 놓습니다.가 필요없 복사합니다.
는 것:
NewStuff ByteArrayToNewStuff(byte[] bytes)
{
GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
try
{
NewStuff stuff = (NewStuff)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(NewStuff));
}
finally
{
handle.Free();
}
return stuff;
}
일반 버전:
T ByteArrayToStructure<T>(byte[] bytes) where T: struct
{
T stuff;
GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
try
{
stuff = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
}
finally
{
handle.Free();
}
return stuff;
}
간단한 버전(필요 unsafe
스위치):
unsafe T ByteArrayToStructure<T>(byte[] bytes) where T : struct
{
fixed (byte* ptr = &bytes[0])
{
return (T)Marshal.PtrToStructure((IntPtr)ptr, typeof(T));
}
}
다른 팁
여기에는 예외 안전 버전의 수락 응답:
public static T ByteArrayToStructure<T>(byte[] bytes) where T : struct
{
var handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
try {
return (T) Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
}
finally {
handle.Free();
}
}
시계 밖으로 포장을 위해 문제입니다.예에게 주신 모든 분야에 있는 명백한 오프셋이기 때문에 모든 것에는 4 바이트로 경계를 그러나 이것은 항상하지 않을 경우입니다.Visual C++팩에 8 바이트의 경계 기본적으로 합니다.
object ByteArrayToStructure(byte[] bytearray, object structureObj, int position)
{
int length = Marshal.SizeOf(structureObj);
IntPtr ptr = Marshal.AllocHGlobal(length);
Marshal.Copy(bytearray, 0, ptr, length);
structureObj = Marshal.PtrToStructure(Marshal.UnsafeAddrOfPinnedArrayElement(bytearray, position), structureObj.GetType());
Marshal.FreeHGlobal(ptr);
return structureObj;
}
이
이 있는 경우 byte[]당신이 사용할 수 있어야 BinaryReader 클래스고 설정 값에 NewStuff 를 사용하여 사용할 수 있 ReadX 방법이 있습니다.