2017-12-26 4 views
-1

c를 나는이 struct이 순서를 뒤집 :마샬링 반바지 #

[StructLayout(LayoutKind.Explicit)] 
private struct Test 
{ 
    [FieldOffset(0)] 
    public readonly short Foo; 

    [FieldOffset(2)] 
    public readonly short Bar; 

    [FieldOffset(4)] 
    public readonly short Baz; 
} 

그리고 다음 바이트 배열 :

var bytes = new byte[] 
{ 
    0x00, 0x01, 
    0x00, 0x05, 
    0xFF, 0xFB 
}; 

그리고 나는 다음과 같은 도우미 함수와 구조에 내 바이트 배열로 변환 :

private static T ByteArrayToStructure<T>(byte[] bytes) 
    where T : struct 
{ 
    GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned); 
    try 
    { 
     return (T) Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T)); 
    } 
    finally 
    { 
     handle.Free(); 
    } 
} 

그래서 다음과 같이 사용합니다 :

var test = ByteArrayToStructure<Test>(bytes); 

Assert.AreEqual(1, test.Foo); 
Assert.AreEqual(5, test.Bar); 
Assert.AreEqual(-5, test.Baz); 

이제 Asserts를 살펴보면 내가 기대하는 바를 분명히 볼 수 있습니다. 결과가 여기에 해당되지 않는다면이 질문이 여기에 있습니다.

그것은 첫 번째 것이 0x0100 대신 0x0001이 될 수 있도록 뭔가, 2 바이트를 튀기는 것 같다, 두 번째 것이 아니라 0x00050x0500로 등장, 마지막 하나는 0xFBFF로 나타 0xFFFB 대신.

이 동작을 비활성화하는 방법이 있습니까?

감사합니다. 당신이 당신의 데이터의 엔디안을 변경하려면

+0

https://stackoverflow.com/questions/2480116/marshalling-a-big-endian-byte-collection-into-a-struct-in-order-to-pull-out-valu –

+1

기대치를 초과했습니다. 현실과 일치한다. 현실과 일치하도록 기대치를 업데이트하는 것을 고려하면 불일치가 사라집니다. 보고있는 동작이 올바른 것입니다. 엔디안을 조정하려면 바이트 배열 끝에서 조정하거나 마샬 러를 작성하십시오. –

+1

"뒤집기"가 없으므로 배열의 바이트 값이 잘못되었습니다. 귀하의 컴퓨터는 리틀 엔디안이며 afaik는 C# 코드를 실행할 수있는 마지막 엔티티 중 하나가 xbox-360입니다. 그래서 작은 끝은 먼저 0x01, 0x00, 0x05 등이되어야합니다. 인간은 빅 엔디안을 선호하는 경향이 있지만 기계와의 전투에서 패배했습니다. 역사 [여기 있습니다] (https://stackoverflow.com/a/36263273/17034). –

답변

0

,이 충분하지 않을 것입니다 :

Array.Reverse(data); 
Test t = ByteArrayToStructure<Test>(bytes); 

당신은 또한 구조체 값의 역순으로 얻을 것이기 때문에 :

t.Foo will be -5 
t.Bar will be 5 
t.Baz will be 1 

당신을 구조의 각 필드 크기를 알고있는 경우에만 배열의 바이트 순서를 반전 할 수 있으므로 배열의 각 바이트 블록을 선택적으로 반대로 할 수 있습니다. 또는,이 같은 배열에서 마샬링 된 후에 당신은 당신의 구조의 각 필드에 바이트 스와핑을 수행해야합니다

Test t = ByteArrayToStructure<Test>(bytes); 
t.Foo = SwapBytes(t.Foo); 
t.Bar = SwapBytes(t.Bar); 
t.Baz = SwapBytes(t.Baz); 

private static short SwapBytes(short value) 
{ 
    return (short)((value >> 8) | ((value & 0xFF) << 8)); 
} 

그러나 나는이 작업을 수행해야하는 경우 코드의 논리가 결함 생각합니다.

@Sam Ax가 자신의 추천에 게시 한 것과 같은 많은 대체 솔루션을 찾고 있습니다. 또는 this one ...하지만 여전히 좋은 습관이라고 생각하지 않습니다.

관련 문제