2012-12-24 26 views
8

tôi đã xác định các cấu trúc sau đây để mô phỏng một đoàn C++ (mà cuối cùng sẽ được sử dụng cho C++ Interop):đoàn trong C#: Cơ cấu thành viên không có vẻ để được Phù hợp

[StructLayout(LayoutKind.Sequential)] 
internal struct STRUCT1 
{ 
    public Guid guid; 

    public String str1; 
    public String str2; 
} 

[StructLayout(LayoutKind.Sequential)] 
internal struct STRUCT2 
{ 
    public Guid guid; 

    public String str1; 
    public String str2; 

    public Int32 i1; 
} 

[StructLayout(LayoutKind.Explicit)] 
internal struct MASTER_STRUCT_UNION 
{ 
    [FieldOffset(0)] 
    public STRUCT1 Struct1; 

    [FieldOffset(0)] 
    public STRUCT2 Struct2; 
} 

[StructLayout(LayoutKind.Sequential)] 
internal struct MASTER_STRUCT 
{ 
    public MASTER_STRUCT_UNION Union; 
} 

Tôi đã viết các bài kiểm tra sau mã mà gán một giá trị để Struct1.guid và kiểm tra cho sự bình đẳng để Struct2.guid:

class Class1 
{ 
    public static void Test() 
    { 
     MASTER_STRUCT ms = new MASTER_STRUCT(); 

     bool match; 
     ms.Union.Struct1.guid = new Guid(0xffeeddcc, 0xbbaa, 0x9988, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0); 

     Console.WriteLine("Struct1.guid:\t\t{0}\n", ms.Union.Struct1.guid.ToString()); 

     Console.WriteLine("Struct2.integer:\t{0:x}", ms.Union.Struct2.i1); 
     Console.WriteLine("Struct2.guid:\t\t{0}", ms.Union.Struct2.guid.ToString()); 


     match = ms.Union.Struct1.guid == ms.Union.Struct2.guid ? true : false; 
    } 
} 

Tại sao Struct2.guid không bằng Struct1.guid và thay vào đó một phân khúc có giá trị Struct2.guid 's dường như chuyển thành 012.? Tất cả các thành viên cấu trúc, IMO, dường như được căn chỉnh.

Trả lời

8

LayoutKind.Sequential chỉ ảnh hưởng đến cấu trúc không được quản lý của cấu trúc này. Điều này là do cấu trúc chứa các loại không thể ghi (cụ thể là, chuỗi).
Nếu chỉ có blittable types có mặt, LayoutKind.Sequential sẽ kiểm soát cả đại diện được quản lý và không được quản lý (reference).

Trong trường hợp của bạn, trình biên dịch quyết định đặt số nguyên trước hai chuỗi trong biểu diễn được quản lý (bạn có thể thấy rằng nếu bạn di chuột qua ms trong khi gỡ lỗi và mở ra STRUCT2).

Bạn có thể khắc phục điều đó bằng cách sử dụng LayoutKind.Explicit trong cả STRUCT1STRUCT2, vì Explicit ảnh hưởng đến cả hai cơ quan đại diện quản lý và không được quản lý cho cả blittable và các loại phi blittable.

+1

Điều đó giải thích rõ điều đó. Cảm ơn bạn. Bây giờ tôi cần phải quyết định xem mã sẽ được dễ dàng hơn để duy trì nếu tôi thay đổi các khai báo chuỗi thành các khai báo IntPtr và So sánh một giá trị chuỗi hoặc sử dụng đề xuất của bạn để sử dụng LayoutKind.Explicit. Nghiêng về phía trước. –

+0

@LJVanKuiken Tôi cũng sẽ đi IntPtrs. Bằng cách này, mã vẫn tương thích với cả 32 và 64 bit, trong khi với Explicit bạn sẽ cần phải sử dụng trình biên dịch có điều kiện cho FieldOffsets hoặc sử dụng đệm 64 bit cho cả 32 và 64 bit (có thể là một bộ nhớ lãng phí). – GSerg

Các vấn đề liên quan