c#编程指南(十二) 平台调用P-INVOKE完全掌握, 结构体边界对齐和内存布局
2010-09-30 22:46:08 来源:WEB开发网第二:特殊的情况下,C++代码使用#pragma pack(n)改变了边界对齐。这里要使用C#要使用 [StructLayout(LayoutKind.Sequential, Pack = N)] 对齐,否则出错。
C++:
1 #pragma pack(1)
2 struct Test2
3 {
4 int test1;
5 char test2;
6 __int64 test3;
7 short test4;
8 };
9 #pragma pack()
10
11 #pragma pack(2)
12 struct Test3
13 {
14 int test1;
15 char test2;
16 __int64 test3;
17 short test4;
18 };
19 #pragma pack()
20
21
22 #pragma pack(4)
23 struct Test4
24 {
25 int test1;
26 char test2;
27 __int64 test3;
28 short test4;
29 };
30 #pragma pack()
C#:
1 [StructLayout(LayoutKind.Sequential, Pack = 1)]
2 struct Test2
3 {
4 public int test1;
5 public char test2;
6 public Int64 test3;
7 public short test4;
8 }
9
10 [StructLayout(LayoutKind.Sequential, Pack = 2)]
11 struct Test3
12 {
13 public int test1;
14 public char test2;
15 public Int64 test3;
16 public short test4;
17 }
18
19 [StructLayout(LayoutKind.Sequential, Pack = 4)]
20 struct Test4
21 {
22 public int test1;
23 public char test2;
24 public Int64 test3;
25 public short test4;
26 }
27
28
29 [DllImport("TestDll")]
30 public static extern IntPtr GetTest2();
31
32 [DllImport("TestDll")]
33 public static extern IntPtr GetTest3();
34
35 [DllImport("TestDll")]
36 public static extern IntPtr GetTest4();
37
38 //#################################
39 IntPtr p2 = GetTest2(); //pack 1
40 Test2 test2 = (Test2)Marshal.PtrToStructure(p2, typeof(Test2));
41
42 IntPtr p3 = GetTest3(); //pack 2
43 Test3 test3 = (Test3)Marshal.PtrToStructure(p3, typeof(Test3));
44
45 IntPtr p4 = GetTest4(); //pack4
46 Test4 test4 = (Test4)Marshal.PtrToStructure(p4, typeof(Test4));
47
48 Console.WriteLine(test2.test1 + test2.test2 + test2.test3 + test2.test4);
49 Console.WriteLine(test3.test1 + test3.test2 + test3.test3 + test3.test4);
50 Console.WriteLine(test4.test1 + test4.test2 + test4.test3 + test4.test4);
最后总结一下,LayoutKind有3个枚举值。LayoutKind.Auto ,LayoutKind.Explicit 和LayoutKind.Sequential.LayoutKind.Auto或者为使用LayoutKind属性的结构体,
进行P-INVOKE调用会抛出异常,改类型不允许进行P-INVOKE调用,LayoutKind.Sequential在内存中顺序布局,一般情况(上面两种)推荐用这个。LayoutKind.Explicit
只推荐特殊情况使用,因为他会明确指定成员的内存offset,很强大也很繁琐。
更多精彩
赞助商链接