2 // Tests for Marshal.StructureToPtr and PtrToStructure
7 using System
.Runtime
.InteropServices
;
12 [StructLayout (LayoutKind
.Sequential
)]
13 public class SimpleObj
{
17 public void test () {}
20 [StructLayout (LayoutKind
.Sequential
)]
21 public struct SimpleStruct2
{
26 [StructLayout (LayoutKind
.Sequential
, CharSet
=CharSet
.Ansi
)]
27 public struct SimpleStruct
{
32 [MarshalAs (UnmanagedType
.ByValArray
, SizeConst
=2)] public short[] a1
;
33 [MarshalAs (UnmanagedType
.ByValTStr
, SizeConst
=4)] public string s1
;
34 public SimpleStruct2 emb1
;
35 public SimpleObj emb2
;
38 [MarshalAs (UnmanagedType
.ByValArray
, SizeConst
=2)]
42 [StructLayout (LayoutKind
.Sequential
, CharSet
=CharSet
.Ansi
)]
43 public struct ByValTStrStruct
{
44 [MarshalAs (UnmanagedType
.ByValTStr
, SizeConst
=4)] public string s1
;
48 [StructLayout (LayoutKind
.Sequential
, CharSet
=CharSet
.Unicode
)]
49 public struct ByValWStrStruct
{
50 [MarshalAs (UnmanagedType
.ByValTStr
, SizeConst
=4)] public string s1
;
54 [StructLayout (LayoutKind
.Sequential
, Pack
=1)]
55 public struct PackStruct1
{
59 [StructLayout (LayoutKind
.Sequential
)]
60 public struct PackStruct2
{
65 [StructLayout (LayoutKind
.Sequential
)]
66 struct InvalidArrayForMarshalingStruct
68 // Missing the following needed directive
69 // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
70 public readonly char[] CharArray
;
73 [StructLayout(LayoutKind
.Sequential
)]
74 struct TwoDimensionalArrayStruct
76 public TwoDimensionalArrayStruct(int[,] vals
)
78 TwoDimensionalArray
= vals
;
81 [MarshalAs(UnmanagedType
.ByValArray
, SizeConst
= 6)]
82 public readonly int[,] TwoDimensionalArray
;
85 public unsafe static int Main (String
[] args
) {
86 if (TestDriver
.RunTests (typeof (Tests
), args
) != 0)
91 public static int test_0_structure_to_ptr () {
92 SimpleStruct ss
= new SimpleStruct ();
93 int size
= Marshal
.SizeOf (typeof (SimpleStruct
));
98 IntPtr p
= Marshal
.AllocHGlobal (size
);
103 ss
.a1
= new short [2];
107 ss
.emb1
= new SimpleStruct2 ();
110 ss
.emb2
= new SimpleObj ();
113 ss
.s2
= "just a test";
115 ss
.a2
= new char [2];
119 Marshal
.StructureToPtr (ss
, p
, false);
120 Type t
= ss
.GetType ();
122 if (Marshal
.ReadInt32 (p
, (int)Marshal
.OffsetOf (t
, "a")) != 1)
124 if (Marshal
.ReadInt32 (p
, (int)Marshal
.OffsetOf (t
, "bool1")) != 1)
126 if (Marshal
.ReadInt32 (p
, (int)Marshal
.OffsetOf (t
, "bool2")) != 0)
128 if (Marshal
.ReadInt32 (p
, (int)Marshal
.OffsetOf (t
, "b")) != 2)
130 if (Marshal
.ReadInt16 (p
, 16) != 6)
132 if (Marshal
.ReadInt16 (p
, 18) != 5)
134 if (Marshal
.ReadByte (p
, 20) != 97)
136 if (Marshal
.ReadByte (p
, 21) != 98)
138 if (Marshal
.ReadByte (p
, 22) != 99)
140 if (Marshal
.ReadByte (p
, 23) != 0)
142 if (Marshal
.ReadInt32 (p
, 24) != 3)
144 if (Marshal
.ReadInt32 (p
, 28) != 4)
146 if (Marshal
.ReadInt32 (p
, 32) != 10)
148 if (Marshal
.ReadInt32 (p
, 36) != 11)
150 if (Marshal
.ReadByte (p
, (int)Marshal
.OffsetOf (t
, "a2")) != 97)
152 if (Marshal
.ReadByte (p
, (int)Marshal
.OffsetOf (t
, "a2") + 1) != 98)
155 SimpleStruct cp
= (SimpleStruct
)Marshal
.PtrToStructure (p
, ss
.GetType ());
160 if (cp
.bool1
!= true)
163 if (cp
.bool2
!= false)
190 if (cp
.s2
!= "just a test")
196 if (cp
.a2
[0] != 'a')
199 if (cp
.a2
[1] != 'b')
204 [StructLayout(LayoutKind
.Sequential
, Pack
= 1, CharSet
= CharSet
.Unicode
)]
205 public struct Struct1
207 [MarshalAs(UnmanagedType
.ByValTStr
, SizeConst
= 8)]
208 public string Field1
;
209 [MarshalAs(UnmanagedType
.ByValTStr
, SizeConst
= 10)]
210 public string Field2
;
211 [MarshalAs(UnmanagedType
.ByValTStr
, SizeConst
= 14)]
212 public string Field3
;
215 public static int test_0_byvaltstr () {
216 ByValTStrStruct s
= new ByValTStrStruct ();
218 IntPtr p2
= Marshal
.AllocHGlobal (Marshal
.SizeOf (typeof (ByValTStrStruct
)));
219 Marshal
.StructureToPtr(s
, p2
, false);
221 /* Check that the ByValTStr is initialized correctly */
222 for (int i
= 0; i
< 4; ++i
)
223 if (Marshal
.ReadByte (p2
, i
) != 0)
229 Marshal
.StructureToPtr(s
, p2
, false);
231 ByValTStrStruct s2
= (ByValTStrStruct
)Marshal
.PtrToStructure (p2
, typeof (ByValTStrStruct
));
233 /* The fourth char is lost because of null-termination */
240 // Check that decoding also respects the size, even when there is no null terminator
241 byte[] data
= Encoding
.ASCII
.GetBytes ("ABCDXXXX");
242 int size
= Marshal
.SizeOf (typeof (ByValTStrStruct
));
243 IntPtr buffer
= Marshal
.AllocHGlobal (size
);
244 Marshal
.Copy (data
, 0, buffer
, size
);
246 s2
= (ByValTStrStruct
)Marshal
.PtrToStructure (buffer
, typeof (ByValTStrStruct
));
253 public static int test_0_byvaltstr_unicode () {
254 ByValWStrStruct s
= new ByValWStrStruct ();
256 IntPtr p2
= Marshal
.AllocHGlobal (Marshal
.SizeOf (typeof (ByValWStrStruct
)));
257 Marshal
.StructureToPtr(s
, p2
, false);
259 /* Check that the ByValWStr is initialized correctly */
260 for (int i
= 0; i
< 8; ++i
)
261 if (Marshal
.ReadByte (p2
, i
) != 0)
267 Marshal
.StructureToPtr(s
, p2
, false);
269 ByValWStrStruct s2
= (ByValWStrStruct
)Marshal
.PtrToStructure (p2
, typeof (ByValWStrStruct
));
271 /* The fourth char is lost because of null-termination */
280 public static int test_0_byvaltstr_max_size () {
281 string buffer
= "12345678123456789012345678901234";
283 IntPtr ptr
= Marshal
.StringToBSTR (buffer
);
285 Struct1 data
= (Struct1
)Marshal
.PtrToStructure (ptr
, typeof (Struct1
));
286 if (data
.Field1
!= "12345678")
288 if (data
.Field2
!= "1234567890")
290 if (data
.Field3
!= "12345678901234")
295 // Check that the 'Pack' directive on a struct changes the min alignment of the struct as well (#12110)
296 public static int test_0_struct_pack () {
297 if (Marshal
.OffsetOf (typeof (PackStruct2
), "s") != new IntPtr (1))
302 public static int test_0_generic_ptr_to_struct () {
303 int size
= Marshal
.SizeOf (typeof (SimpleStruct2
));
304 IntPtr p
= Marshal
.AllocHGlobal (size
);
306 Marshal
.WriteInt32 (p
, 0, 1); //a
307 Marshal
.WriteInt32 (p
, 4, 2); //a
309 var s
= Marshal
.PtrToStructure
<SimpleStruct2
> (p
);
318 public static int test_0_invalid_array_throws () {
319 var ptr
= Marshal
.AllocHGlobal(Marshal
.SizeOf (typeof (InvalidArrayForMarshalingStruct
)));
321 Marshal
.PtrToStructure (ptr
, typeof (InvalidArrayForMarshalingStruct
));
323 catch (MarshalDirectiveException e
) {
329 public static int test_0_multidimentional_arrays () {
330 var structToMarshal
= new TwoDimensionalArrayStruct (new[, ] { {1, 2, 3}
, {4, 5, 6}
});
331 var ptr
= Marshal
.AllocHGlobal (Marshal
.SizeOf (structToMarshal
));
332 Marshal
.StructureToPtr (structToMarshal
, ptr
, false);
334 if(((int*)ptr
)[4] == 5)
340 struct GenericStruct
<T
>
344 public bool b
; // make struct non-blittable
347 struct NonGenericStruct
351 public bool b
; // make struct non-blittable
354 struct StructWithGenericField
356 public GenericStruct
<int> gs
;
359 struct StructWithNonGenericField
361 public NonGenericStruct ngs
;
364 public static int test_0_marshal_generic_struct () {
365 var structToMarshal
= new StructWithNonGenericField () { ngs = new NonGenericStruct {t1 = 1, t2 =2}
};
366 var ptr
= Marshal
.AllocHGlobal (Marshal
.SizeOf (structToMarshal
));
367 Marshal
.StructureToPtr(structToMarshal
, ptr
, false);
368 var genericStruct
= (StructWithGenericField
)Marshal
.PtrToStructure(ptr
, typeof(StructWithGenericField
));
369 if (genericStruct
.gs
.t1
== 1)