/
marshal7.cs
239 lines (206 loc) · 5.47 KB
/
marshal7.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
using System;
using System.Reflection;
using System.Runtime.InteropServices;
public class Test
{
[StructLayout(LayoutKind.Sequential, Size=32)]
public class TestStruct1
{
public int a;
}
[StructLayout(LayoutKind.Sequential, Size=32)]
public class TestStruct2
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=16)]
public string a;
public int b;
}
[StructLayout(LayoutKind.Sequential, Size=32)]
public class TestStruct3 : TestStruct2
{
public int c;
}
[StructLayout (LayoutKind.Sequential)]
public class TestStruct4
{
[MarshalAs (UnmanagedType.Interface)]
object itf;
}
[StructLayout (LayoutKind.Sequential)]
public class TestStruct5
{
[MarshalAs (UnmanagedType.IUnknown)]
object itf;
}
[StructLayout (LayoutKind.Sequential)]
public class TestStruct6
{
[MarshalAs (UnmanagedType.IDispatch)]
object itf;
}
[StructLayout (LayoutKind.Sequential)]
public class TestStruct7
{
[MarshalAs (UnmanagedType.Struct)]
object itf;
}
// Size should be 16 in both 32 and 64 bits win/linux
// Size should be 12 on 32bits OSX size alignment of long is 4
[StructLayout (LayoutKind.Explicit)]
struct TestStruct8 {
[FieldOffset (0)]
public int a;
[FieldOffset (4)]
public ulong b;
}
// Size should be 12 in both 32 and 64 bits
[StructLayout (LayoutKind.Explicit, Size=12)]
struct TestStruct9 {
[FieldOffset (0)]
public int a;
[FieldOffset (4)]
public ulong b;
}
// Size should be 16 in both 32 and 64 bits
// Size should be 12 on 32bits OSX size alignment of long is 4
[StructLayout (LayoutKind.Explicit)]
struct TestStruct10 {
[FieldOffset (0)]
public int a;
[FieldOffset (3)]
public ulong b;
}
// Size should be 11 in both 32 and 64 bits
[StructLayout (LayoutKind.Explicit, Size=11)]
struct TestStruct11 {
[FieldOffset (0)]
public int a;
[FieldOffset (3)]
public ulong b;
}
[StructLayout (LayoutKind.Explicit, Pack=1)]
struct TestStruct12 {
[FieldOffset (0)]
public short a;
[FieldOffset (2)]
public int b;
}
// Size should always be 12, since pack = 0, size = 0 and min alignment = 4
//When pack is not set, we default to 8, so min (8, min alignment) -> 4
[StructLayout (LayoutKind.Explicit)]
struct TestStruct13 {
[FieldOffset(0)]
int one;
[FieldOffset(4)]
int two;
[FieldOffset(8)]
int three;
}
// Size should always be 12, since pack = 8, size = 0 and min alignment = 4
//It's aligned to min (pack, min alignment) -> 4
[StructLayout (LayoutKind.Explicit)]
struct TestStruct14 {
[FieldOffset(0)]
int one;
[FieldOffset(4)]
int two;
[FieldOffset(8)]
int three;
}
static bool IsOSX ()
{
return (int)typeof (Environment).GetMethod ("get_Platform", BindingFlags.Static | BindingFlags.NonPublic).Invoke (null, null) == 6;
}
public unsafe static int Main ()
{
///
/// Testing simple struct size
///
if(Marshal.SizeOf(typeof(TestStruct1)) != 32)
{
return 1;
}
TestStruct1 myStruct = new TestStruct1();
myStruct.a = 0x12345678;
IntPtr p = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(TestStruct1)));
Marshal.StructureToPtr(myStruct, p, false);
Type testType = typeof(TestStruct1);
if (Marshal.ReadInt32(p, (int)Marshal.OffsetOf(testType, "a")) != myStruct.a)
return 2;
Marshal.FreeHGlobal(p);
///
/// Testing struct size with ByValTStr string
///
if(Marshal.SizeOf(typeof(TestStruct2)) != 32)
return 3;
TestStruct2 myStruct2 = new TestStruct2();
myStruct2.b = 0x12345678;
p = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(TestStruct2)));
Marshal.StructureToPtr(myStruct2, p, false);
Type testType2 = typeof(TestStruct2);
if (Marshal.ReadInt32(p, (int)Marshal.OffsetOf(testType2, "b")) != myStruct2.b)
return 4;
Marshal.FreeHGlobal(p);
///
/// Test structure size and struct with inheritance
///
if(Marshal.SizeOf(typeof(TestStruct3)) != 64)
return 5;
TestStruct3 myStruct3 = new TestStruct3();
myStruct3.b = 0x12345678;
myStruct3.c = 0x76543210;
p = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(TestStruct3)));
Marshal.StructureToPtr(myStruct3, p, false);
Type testType3 = typeof(TestStruct3);
if(Marshal.ReadInt32(p, (int)Marshal.OffsetOf(testType3, "b")) != myStruct3.b)
return 6;
if (Marshal.ReadInt32(p, (int)Marshal.OffsetOf(testType3, "c")) != myStruct3.c)
return 7;
Marshal.FreeHGlobal(p);
///
/// Also make sure OffsetOf returns the correct Exception.
///
try {
Marshal.OffsetOf(testType3, "blah");
return 8;
}
catch(ArgumentException e) {
/// Way to go :)
}
catch(Exception e) {
return 9;
}
// test size of structs with objects
if (Marshal.SizeOf (typeof (TestStruct4)) != IntPtr.Size)
return 10;
if (Marshal.SizeOf (typeof (TestStruct5)) != IntPtr.Size)
return 11;
if (Marshal.SizeOf (typeof (TestStruct6)) != IntPtr.Size)
return 12;
// a VARIANT is
if (Marshal.SizeOf (typeof (TestStruct7)) != 16)
return 13;
if (IsOSX () && IntPtr.Size == 4) {
if (Marshal.SizeOf (typeof (TestStruct8)) != 12)
return 14;
if (Marshal.SizeOf (typeof (TestStruct10)) != 12)
return 16;
} else {
if (Marshal.SizeOf (typeof (TestStruct8)) != 16)
return 14;
if (Marshal.SizeOf (typeof (TestStruct10)) != 16)
return 16;
}
if (Marshal.SizeOf (typeof (TestStruct9)) != 12)
return 15;
if (Marshal.SizeOf (typeof (TestStruct11)) != 11)
return 17;
if (Marshal.SizeOf (typeof (TestStruct12)) != 6)
return 18;
if (Marshal.SizeOf (typeof (TestStruct13)) != 12)
return 19;
if (Marshal.SizeOf (typeof (TestStruct14)) != 12)
return 20;
return 0;
}
}