문제

무엇을 할 수있는 가장 좋은 방법이 될 것이를 채우기 위 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 방법이 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top