[jit] In native-to-managed wrappers, emit the initlocals code for vtypes after the...
[mono.git] / mono / tests / pinvoke3.cs
1 //
2 // pinvoke3.cs:
3 //
4 //  Tests for native->managed marshalling
5 //
6
7 using System;
8 using System.Text;
9 using System.Runtime.InteropServices;
10 using System.Threading;
11
12 public class Tests {
13
14         [StructLayout (LayoutKind.Sequential)]
15         public struct SimpleStruct {
16                 public bool a;
17                 public bool b;
18                 public bool c;
19                 public string d;
20                 [MarshalAs(UnmanagedType.LPWStr)]
21                 public string d2;
22         }
23
24         [StructLayout (LayoutKind.Sequential)]
25         public class SimpleClass {
26                 public bool a;
27                 public bool b;
28                 public bool c;
29                 public string d;
30         }
31
32         public static SimpleStruct delegate_test_struct (SimpleStruct ss)
33         {
34                 SimpleStruct res;
35
36                 res.a = !ss.a;
37                 res.b = !ss.b;
38                 res.c = !ss.c;
39                 res.d = ss.d + "-RES";
40                 res.d2 = ss.d2 + "-RES";
41
42                 return res;
43         }
44
45         public static int delegate_test_struct_byref (int a, ref SimpleStruct ss, int b)
46         {
47                 if (a == 1 && b == 2 && ss.a && !ss.b && ss.c && ss.d == "TEST2") {
48                         ss.a = true;
49                         ss.b = true;
50                         ss.c = true;
51                         ss.d = "TEST3";
52                         return 0;
53                 }
54
55                 return 1;
56         }
57
58         public static int delegate_test_struct_out (int a, out SimpleStruct ss, int b)
59         {
60                 ss.a = true;
61                 ss.b = true;
62                 ss.c = true;
63                 ss.d = "TEST3";
64                 ss.d2 = "TEST4";
65
66                 return 0;
67         }
68
69         public static int delegate_test_struct_in (int a, [In] ref SimpleStruct ss, int b)
70         {
71                 if (a == 1 && b == 2 && ss.a && !ss.b && ss.c && ss.d == "TEST2") {
72                         ss.a = true;
73                         ss.b = true;
74                         ss.c = true;
75                         ss.d = "TEST3";
76                         return 0;
77                 }
78
79                 return 1;
80         }
81
82         public static SimpleClass delegate_test_class (SimpleClass ss)
83         {
84                 if (ss == null)
85                         return null;
86
87                 if (! (!ss.a && ss.b && !ss.c && ss.d == "TEST"))
88                         return null;
89
90                 SimpleClass res = ss;
91
92                 return res;
93         }
94
95         public static int delegate_test_class_byref (ref SimpleClass ss)
96         {
97                 if (ss == null)
98                         return -1;
99
100                 if (!ss.a && ss.b && !ss.c && ss.d == "TEST") {
101                         ss.a = true;
102                         ss.b = false;
103                         ss.c = true;
104                         ss.d = "RES";
105
106                         return 0;
107                 }
108
109                 return 1;
110         }
111
112         public static int delegate_test_class_out (out SimpleClass ss)
113         {
114                 ss = new SimpleClass ();
115                 ss.a = true;
116                 ss.b = false;
117                 ss.c = true;
118                 ss.d = "RES";
119
120                 return 0;
121         }
122
123         public static int delegate_test_primitive_byref (ref int i)
124         {
125                 if (i != 1)
126                         return 1;
127                 
128                 i = 2;
129                 return 0;
130         }
131
132         public static int delegate_test_string_marshalling (string s)
133         {
134                 return s == "ABC" ? 0 : 1;
135         }
136
137         public static int delegate_test_string_builder_marshalling (StringBuilder s)
138         {
139                 if (s == null)
140                         return 2;
141                 else
142                         return s.ToString () == "ABC" ? 0 : 1;
143         }
144
145         [DllImport ("libtest", EntryPoint="mono_test_ref_vtype")]
146         public static extern int mono_test_ref_vtype (int a, ref SimpleStruct ss, int b, TestDelegate d);
147
148         public delegate int OutStructDelegate (int a, out SimpleStruct ss, int b);
149
150         public delegate int InStructDelegate (int a, [In] ref SimpleStruct ss, int b);
151
152         [DllImport ("libtest", EntryPoint="mono_test_marshal_out_struct")]
153         public static extern int mono_test_marshal_out_struct (int a, out SimpleStruct ss, int b, OutStructDelegate d);
154
155         [DllImport ("libtest", EntryPoint="mono_test_marshal_in_struct")]
156         public static extern int mono_test_marshal_in_struct (int a, ref SimpleStruct ss, int b, InStructDelegate d);
157         
158         [DllImport ("libtest", EntryPoint="mono_test_marshal_delegate2")]
159         public static extern int mono_test_marshal_delegate2 (SimpleDelegate2 d);
160
161         [DllImport ("libtest", EntryPoint="mono_test_marshal_delegate4")]
162         public static extern int mono_test_marshal_delegate4 (SimpleDelegate4 d);
163
164         [DllImport ("libtest", EntryPoint="mono_test_marshal_delegate5")]
165         public static extern int mono_test_marshal_delegate5 (SimpleDelegate5 d);
166
167         [DllImport ("libtest", EntryPoint="mono_test_marshal_delegate6")]
168         public static extern int mono_test_marshal_delegate6 (SimpleDelegate5 d);
169
170         [DllImport ("libtest", EntryPoint="mono_test_marshal_delegate7")]
171         public static extern int mono_test_marshal_delegate7 (SimpleDelegate7 d);
172
173         [DllImport ("libtest", EntryPoint="mono_test_marshal_delegate8", CharSet=CharSet.Unicode)]
174         public static extern int mono_test_marshal_delegate8 (SimpleDelegate8 d, string s);
175
176         [DllImport ("libtest", EntryPoint="mono_test_marshal_delegate9")]
177         public static extern int mono_test_marshal_delegate9 (SimpleDelegate9 d, return_int_delegate d2);
178
179         [DllImport ("libtest", EntryPoint="mono_test_marshal_delegate10")]
180         public static extern int mono_test_marshal_delegate10 (SimpleDelegate9 d);
181
182         [DllImport ("libtest", EntryPoint="mono_test_marshal_delegate8")]
183         public static extern int mono_test_marshal_delegate11 (SimpleDelegate11 d, string s);
184
185         [DllImport ("libtest", EntryPoint="mono_test_marshal_primitive_byref_delegate")]
186         public static extern int mono_test_marshal_primitive_byref_delegate (PrimitiveByrefDelegate d);
187
188         [DllImport ("libtest", EntryPoint="mono_test_marshal_return_delegate_delegate")]
189         public static extern int mono_test_marshal_return_delegate_delegate (ReturnDelegateDelegate d);
190
191         [DllImport ("libtest", EntryPoint="mono_test_marshal_delegate_ref_delegate")]
192         public static extern int mono_test_marshal_delegate_ref_delegate (DelegateByrefDelegate del);
193
194         [DllImport ("libtest", EntryPoint="mono_test_marshal_virtual_delegate")]
195         public static extern int mono_test_marshal_virtual_delegate (VirtualDelegate del);
196
197         [DllImport ("libtest", EntryPoint="mono_test_marshal_icall_delegate")]
198         public static extern int mono_test_marshal_icall_delegate (IcallDelegate del);
199
200         public delegate string IcallDelegate (IntPtr p);
201
202         public delegate int TestDelegate (int a, ref SimpleStruct ss, int b);
203
204         public delegate SimpleStruct SimpleDelegate2 (SimpleStruct ss);
205
206         public delegate SimpleClass SimpleDelegate4 (SimpleClass ss);
207
208         public delegate int SimpleDelegate5 (ref SimpleClass ss);
209
210         public delegate int SimpleDelegate7 (out SimpleClass ss);
211
212         public delegate int SimpleDelegate8 ([MarshalAs (UnmanagedType.LPWStr)] string s1);
213
214         public delegate int return_int_delegate (int i);
215
216         public delegate int SimpleDelegate9 (return_int_delegate del);
217
218         public delegate int SimpleDelegate11 (StringBuilder s1);
219
220         public delegate int PrimitiveByrefDelegate (ref int i);
221
222         public delegate return_int_delegate ReturnDelegateDelegate ();
223
224         public delegate int DelegateByrefDelegate (ref return_int_delegate del);
225
226         public delegate int VirtualDelegate (int i);
227
228         public static int Main () {
229                 return TestDriver.RunTests (typeof (Tests));
230         }
231
232         /* Test structures as arguments and return values of delegates */
233         public static int test_0_marshal_struct_delegate () {
234                 SimpleDelegate2 d = new SimpleDelegate2 (delegate_test_struct);
235
236                 return mono_test_marshal_delegate2 (d);
237         }
238
239         /* Test structures as byref arguments of delegates */
240         public static int test_0_marshal_byref_struct_delegate () {
241                 SimpleStruct ss = new SimpleStruct ();
242                 TestDelegate d = new TestDelegate (delegate_test_struct_byref);
243                 
244                 ss.b = true;
245                 ss.d = "TEST1";
246
247                 if (mono_test_ref_vtype (1, ref ss, 2, d) != 0)
248                         return 1;
249
250                 if (! (ss.a && ss.b && ss.c && ss.d == "TEST3"))
251                         return 2;
252                 
253                 return 0;
254         }
255
256         /* Test structures as out arguments of delegates */
257         public static int test_0_marshal_out_struct_delegate () {
258                 SimpleStruct ss = new SimpleStruct ();
259                 OutStructDelegate d = new OutStructDelegate (delegate_test_struct_out);
260
261                 return mono_test_marshal_out_struct (1, out ss, 2, d);
262         }
263
264         /* Test structures as in arguments of delegates */
265         public static int test_0_marshal_in_struct_delegate () {
266                 SimpleStruct ss = new SimpleStruct () { a = true, b = false, c = true, d = "TEST2" };
267                 InStructDelegate d = new InStructDelegate (delegate_test_struct_in);
268
269                 return mono_test_marshal_in_struct (1, ref ss, 2, d);
270         }
271
272         /* Test classes as arguments and return values of delegates */
273         public static int test_0_marshal_class_delegate () {
274                 SimpleDelegate4 d = new SimpleDelegate4 (delegate_test_class);
275
276                 return mono_test_marshal_delegate4 (d);
277         }
278
279         /* Test classes as byref arguments of delegates */
280         public static int test_0_marshal_byref_class_delegate () {
281                 SimpleDelegate5 d = new SimpleDelegate5 (delegate_test_class_byref);
282
283                 return mono_test_marshal_delegate5 (d);
284         }
285
286         /* Test classes as out arguments of delegates */
287         public static int test_0_marshal_out_class_delegate () {
288                 SimpleDelegate7 d = new SimpleDelegate7 (delegate_test_class_out);
289
290                 return mono_test_marshal_delegate7 (d);
291         }
292
293         /* Test string marshalling with delegates */
294         public static int test_0_marshal_string_delegate () {
295                 SimpleDelegate8 d = new SimpleDelegate8 (delegate_test_string_marshalling);
296
297                 return mono_test_marshal_delegate8 (d, "ABC");
298         }
299
300         /* Test string builder marshalling with delegates */
301         public static int test_0_marshal_string_builder_delegate () {
302                 SimpleDelegate11 d = new SimpleDelegate11 (delegate_test_string_builder_marshalling);
303
304                 if (mono_test_marshal_delegate11 (d, null) != 2)
305                         return 2;
306
307                 return mono_test_marshal_delegate11 (d, "ABC");
308         }
309
310         /* Test that the delegate wrapper correctly catches null byref arguments */
311         public static int test_0_marshal_byref_class_delegate_null () {
312                 SimpleDelegate5 d = new SimpleDelegate5 (delegate_test_class_byref);
313                 
314                 try {
315                         mono_test_marshal_delegate6 (d);
316                         return 1;
317                 }
318                 catch (ArgumentNullException ex) {
319                         return 0;
320                 }
321         }
322
323         static int return_self (int i) {
324                 return i;
325         }
326
327         static int call_int_delegate (return_int_delegate d) {
328                 return d (55);
329         }
330
331         public static int test_55_marshal_delegate_delegate () {
332                 SimpleDelegate9 d = new SimpleDelegate9 (call_int_delegate);
333
334                 return mono_test_marshal_delegate9 (d, new return_int_delegate (return_self));
335         }
336
337         public static int test_0_marshal_primitive_byref_delegate () {
338                 PrimitiveByrefDelegate d = new PrimitiveByrefDelegate (delegate_test_primitive_byref);
339
340                 return mono_test_marshal_primitive_byref_delegate (d);
341         }
342
343         public static return_int_delegate return_delegate () {
344                 return new return_int_delegate (return_self);
345         }
346
347         public static int test_55_marshal_return_delegate_delegate () {
348                 return mono_test_marshal_return_delegate_delegate (new ReturnDelegateDelegate (return_delegate));
349         }
350
351         public static int return_plus_1 (int i) {
352                 return i + 1;
353         }
354
355         public static int ref_delegate_delegate (ref return_int_delegate del) {
356                 del = return_plus_1;
357                 return 0;
358         }
359
360         public static int test_55_marshal_delegate_ref_delegate () {
361                 var del = new DelegateByrefDelegate (ref_delegate_delegate);
362                 return mono_test_marshal_delegate_ref_delegate (del);
363         }
364
365         /* Passing and returning strings */
366
367         public delegate String ReturnStringDelegate (String s);
368
369         [DllImport ("libtest", EntryPoint="mono_test_return_string")]
370         public static extern String mono_test_marshal_return_string_delegate (ReturnStringDelegate d);
371
372         public static String managed_return_string (String s) {
373                 if (s != "TEST")
374                         return "";
375                 else
376                         return "12345";
377         }
378
379         public static int test_0_marshal_return_string_delegate () {
380                 ReturnStringDelegate d = new ReturnStringDelegate (managed_return_string);
381                 String s = mono_test_marshal_return_string_delegate (d);
382
383                 return (s == "12345") ? 0 : 1;
384         }
385
386         /* Passing and returning enums */
387
388         public enum FooEnum {
389                 Foo1,
390                 Foo2,
391                 Foo3
392         };
393
394         public delegate FooEnum ReturnEnumDelegate (FooEnum e);
395
396         [DllImport ("libtest", EntryPoint="mono_test_marshal_return_enum_delegate")]
397         public static extern int mono_test_marshal_return_enum_delegate (ReturnEnumDelegate d);
398
399         public static FooEnum managed_return_enum (FooEnum e) {
400                 return (FooEnum)((int)e + 1);
401         }
402
403         public static int test_0_marshal_return_enum_delegate () {
404                 ReturnEnumDelegate d = new ReturnEnumDelegate (managed_return_enum);
405                 FooEnum e = (FooEnum)mono_test_marshal_return_enum_delegate (d);
406
407                 return e == FooEnum.Foo3 ? 0 : 1;
408         }
409
410         /* Passing and returning blittable structs */
411
412         [StructLayout (LayoutKind.Sequential)]
413         public struct BlittableStruct {
414                 public int a, b, c;
415                 public long d;
416         }
417
418         public static BlittableStruct delegate_test_blittable_struct (BlittableStruct ss)
419         {
420                 BlittableStruct res;
421
422                 res.a = -ss.a;
423                 res.b = -ss.b;
424                 res.c = -ss.c;
425                 res.d = -ss.d;
426
427                 return res;
428         }
429
430         public delegate BlittableStruct SimpleDelegate10 (BlittableStruct ss);
431
432         [DllImport ("libtest", EntryPoint="mono_test_marshal_blittable_struct_delegate")]
433         public static extern int mono_test_marshal_blittable_struct_delegate (SimpleDelegate10 d);
434
435         public static int test_0_marshal_blittable_struct_delegate () {
436                 return mono_test_marshal_blittable_struct_delegate (new SimpleDelegate10 (delegate_test_blittable_struct));
437         }
438
439         /*
440          * Passing and returning small structs
441          */
442
443         /* TEST 1: 4 byte long INTEGER struct */
444
445         [StructLayout (LayoutKind.Sequential)]
446         public struct SmallStruct1 {
447                 public int i;
448         }
449
450         public static SmallStruct1 delegate_test_struct (SmallStruct1 ss) {
451                 SmallStruct1 res;
452
453                 res.i = -ss.i;
454                 
455                 return res;
456         }
457
458         public delegate SmallStruct1 SmallStructDelegate1 (SmallStruct1 ss);
459
460         [DllImport ("libtest", EntryPoint="mono_test_marshal_small_struct_delegate1")]
461         public static extern int mono_test_marshal_small_struct_delegate (SmallStructDelegate1 d);
462
463         public static int test_0_marshal_small_struct_delegate1 () {
464                 return mono_test_marshal_small_struct_delegate (new SmallStructDelegate1 (delegate_test_struct));
465         }
466
467         /* TEST 2: 2+2 byte long INTEGER struct */
468
469         [StructLayout (LayoutKind.Sequential)]
470         public struct SmallStruct2 {
471                 public short i, j;
472         }
473
474         public static SmallStruct2 delegate_test_struct (SmallStruct2 ss) {
475                 SmallStruct2 res;
476
477                 res.i = (short)-ss.i;
478                 res.j = (short)-ss.j;
479                 
480                 return res;
481         }
482
483         public delegate SmallStruct2 SmallStructDelegate2 (SmallStruct2 ss);
484
485         [DllImport ("libtest", EntryPoint="mono_test_marshal_small_struct_delegate2")]
486         public static extern int mono_test_marshal_small_struct_delegate (SmallStructDelegate2 d);
487
488         public static int test_0_marshal_small_struct_delegate2 () {
489                 return mono_test_marshal_small_struct_delegate (new SmallStructDelegate2 (delegate_test_struct));
490         }
491
492         /* TEST 3: 2+1 byte long INTEGER struct */
493
494         [StructLayout (LayoutKind.Sequential)]
495         public struct SmallStruct3 {
496                 public short i;
497                 public byte j;
498         }
499
500         public static SmallStruct3 delegate_test_struct (SmallStruct3 ss) {
501                 SmallStruct3 res;
502
503                 res.i = (short)-ss.i;
504                 res.j = (byte)-ss.j;
505                 
506                 return res;
507         }
508
509         public delegate SmallStruct3 SmallStructDelegate3 (SmallStruct3 ss);
510
511         [DllImport ("libtest", EntryPoint="mono_test_marshal_small_struct_delegate3")]
512         public static extern int mono_test_marshal_small_struct_delegate (SmallStructDelegate3 d);
513
514         public static int test_0_marshal_small_struct_delegate3 () {
515                 return mono_test_marshal_small_struct_delegate (new SmallStructDelegate3 (delegate_test_struct));
516         }
517
518         /* TEST 4: 2 byte long INTEGER struct */
519
520         [StructLayout (LayoutKind.Sequential)]
521         public struct SmallStruct4 {
522                 public short i;
523         }
524
525         public static SmallStruct4 delegate_test_struct (SmallStruct4 ss) {
526                 SmallStruct4 res;
527
528                 res.i = (short)-ss.i;
529                 
530                 return res;
531         }
532
533         public delegate SmallStruct4 SmallStructDelegate4 (SmallStruct4 ss);
534
535         [DllImport ("libtest", EntryPoint="mono_test_marshal_small_struct_delegate4")]
536         public static extern int mono_test_marshal_small_struct_delegate (SmallStructDelegate4 d);
537
538         public static int test_0_marshal_small_struct_delegate4 () {
539                 return mono_test_marshal_small_struct_delegate (new SmallStructDelegate4 (delegate_test_struct));
540         }
541
542         /* TEST 5: 8 byte long INTEGER struct */
543
544         [StructLayout (LayoutKind.Sequential)]
545         public struct SmallStruct5 {
546                 public long l;
547         }
548
549         public static SmallStruct5 delegate_test_struct (SmallStruct5 ss) {
550                 SmallStruct5 res;
551
552                 res.l = -ss.l;
553                 
554                 return res;
555         }
556
557         public delegate SmallStruct5 SmallStructDelegate5 (SmallStruct5 ss);
558
559         [DllImport ("libtest", EntryPoint="mono_test_marshal_small_struct_delegate5")]
560         public static extern int mono_test_marshal_small_struct_delegate (SmallStructDelegate5 d);
561
562         public static int test_0_marshal_small_struct_delegate5 () {
563                 return mono_test_marshal_small_struct_delegate (new SmallStructDelegate5 (delegate_test_struct));
564         }
565
566         /* TEST 6: 4+4 byte long INTEGER struct */
567
568         [StructLayout (LayoutKind.Sequential)]
569         public struct SmallStruct6 {
570                 public int i, j;
571         }
572
573         public static SmallStruct6 delegate_test_struct (SmallStruct6 ss) {
574                 SmallStruct6 res;
575
576                 res.i = -ss.i;
577                 res.j = -ss.j;
578                 
579                 return res;
580         }
581
582         public delegate SmallStruct6 SmallStructDelegate6 (SmallStruct6 ss);
583
584         [DllImport ("libtest", EntryPoint="mono_test_marshal_small_struct_delegate6")]
585         public static extern int mono_test_marshal_small_struct_delegate (SmallStructDelegate6 d);
586
587         public static int test_0_marshal_small_struct_delegate6 () {
588                 return mono_test_marshal_small_struct_delegate (new SmallStructDelegate6 (delegate_test_struct));
589         }
590
591         /* TEST 7: 4+2 byte long INTEGER struct */
592
593         [StructLayout (LayoutKind.Sequential)]
594         public struct SmallStruct7 {
595                 public int i;
596                 public short j;
597         }
598
599         public static SmallStruct7 delegate_test_struct (SmallStruct7 ss) {
600                 SmallStruct7 res;
601
602                 res.i = -ss.i;
603                 res.j = (short)-ss.j;
604                 
605                 return res;
606         }
607
608         public delegate SmallStruct7 SmallStructDelegate7 (SmallStruct7 ss);
609
610         [DllImport ("libtest", EntryPoint="mono_test_marshal_small_struct_delegate7")]
611         public static extern int mono_test_marshal_small_struct_delegate (SmallStructDelegate7 d);
612
613         public static int test_0_marshal_small_struct_delegate7 () {
614                 return mono_test_marshal_small_struct_delegate (new SmallStructDelegate7 (delegate_test_struct));
615         }
616
617         /* TEST 8: 4 byte long FLOAT struct */
618
619         [StructLayout (LayoutKind.Sequential)]
620         public struct SmallStruct8 {
621                 public float i;
622         }
623
624         public static SmallStruct8 delegate_test_struct (SmallStruct8 ss) {
625                 SmallStruct8 res;
626
627                 res.i = -ss.i;
628                 
629                 return res;
630         }
631
632         public delegate SmallStruct8 SmallStructDelegate8 (SmallStruct8 ss);
633
634         [DllImport ("libtest", EntryPoint="mono_test_marshal_small_struct_delegate8")]
635         public static extern int mono_test_marshal_small_struct_delegate (SmallStructDelegate8 d);
636
637         public static int test_0_marshal_small_struct_delegate8 () {
638                 return mono_test_marshal_small_struct_delegate (new SmallStructDelegate8 (delegate_test_struct));
639         }
640
641         /* TEST 9: 8 byte long FLOAT struct */
642
643         [StructLayout (LayoutKind.Sequential)]
644         public struct SmallStruct9 {
645                 public double i;
646         }
647
648         public static SmallStruct9 delegate_test_struct (SmallStruct9 ss) {
649                 SmallStruct9 res;
650
651                 res.i = -ss.i;
652                 
653                 return res;
654         }
655
656         public delegate SmallStruct9 SmallStructDelegate9 (SmallStruct9 ss);
657
658         [DllImport ("libtest", EntryPoint="mono_test_marshal_small_struct_delegate9")]
659         public static extern int mono_test_marshal_small_struct_delegate (SmallStructDelegate9 d);
660
661         public static int test_0_marshal_small_struct_delegate9 () {
662                 return mono_test_marshal_small_struct_delegate (new SmallStructDelegate9 (delegate_test_struct));
663         }
664
665         /* TEST 10: 4+4 byte long FLOAT struct */
666
667         [StructLayout (LayoutKind.Sequential)]
668         public struct SmallStruct10 {
669                 public float i;
670                 public float j;
671         }
672
673         public static SmallStruct10 delegate_test_struct (SmallStruct10 ss) {
674                 SmallStruct10 res;
675
676                 res.i = -ss.i;
677                 res.j = -ss.j;
678                 
679                 return res;
680         }
681
682         public delegate SmallStruct10 SmallStructDelegate10 (SmallStruct10 ss);
683
684         [DllImport ("libtest", EntryPoint="mono_test_marshal_small_struct_delegate10")]
685         public static extern int mono_test_marshal_small_struct_delegate (SmallStructDelegate10 d);
686
687         public static int test_0_marshal_small_struct_delegate10 () {
688                 return mono_test_marshal_small_struct_delegate (new SmallStructDelegate10 (delegate_test_struct));
689         }
690
691         /* TEST 11: 4+4 byte long MIXED struct */
692
693         [StructLayout (LayoutKind.Sequential)]
694         public struct SmallStruct11 {
695                 public float i;
696                 public int j;
697         }
698
699         public static SmallStruct11 delegate_test_struct (SmallStruct11 ss) {
700                 SmallStruct11 res;
701
702                 res.i = -ss.i;
703                 res.j = -ss.j;
704                 
705                 return res;
706         }
707
708         public delegate SmallStruct11 SmallStructDelegate11 (SmallStruct11 ss);
709
710         [DllImport ("libtest", EntryPoint="mono_test_marshal_small_struct_delegate11")]
711         public static extern int mono_test_marshal_small_struct_delegate (SmallStructDelegate11 d);
712
713         public static int test_0_marshal_small_struct_delegate11 () {
714                 return mono_test_marshal_small_struct_delegate (new SmallStructDelegate11 (delegate_test_struct));
715         }
716
717         /*
718          * Passing arrays
719          */
720         public delegate int ArrayDelegate1 (int i, 
721                                                                                 string j, 
722                                                                                 [In, MarshalAs(UnmanagedType.LPArray, 
723                                                                                                            ArraySubType=UnmanagedType.LPStr, SizeParamIndex=0)] string[] arr);
724
725         [DllImport ("libtest", EntryPoint="mono_test_marshal_array_delegate")]
726         public static extern int mono_test_marshal_array_delegate1 (string[] arr, int len, ArrayDelegate1 d);
727
728         public static int array_delegate1 (int i, string j, string[] arr) {
729                 if (arr.Length != 2)
730                         return 1;
731                 if ((arr [0] != "ABC") || (arr [1] != "DEF"))
732                         return 2;
733                 return 0;
734         }
735
736         public static int test_0_marshal_array_delegate_string () {     
737                 string[] arr = new string [] { "ABC", "DEF" };
738                 return mono_test_marshal_array_delegate1 (arr, arr.Length, new ArrayDelegate1 (array_delegate1));
739         }
740
741         public static int array_delegate2 (int i, string j, string[] arr) {
742                 return (arr == null) ? 0 : 1;
743         }
744
745         public static int test_0_marshal_array_delegate_null () {       
746                 return mono_test_marshal_array_delegate1 (null, 0, new ArrayDelegate1 (array_delegate2));
747         }
748
749         public delegate int ArrayDelegateBlittable (int i, string j,
750                                                                                 [In, MarshalAs(UnmanagedType.LPArray,
751                                                                                                            ArraySubType=UnmanagedType.LPStr, SizeParamIndex=0)] int[] arr);
752
753         [DllImport ("libtest", EntryPoint="mono_test_marshal_array_delegate")]
754         public static extern int mono_test_marshal_array_delegate1 (string[] arr, int len, ArrayDelegateBlittable d);
755
756         public static int array_delegate_null_blittable (int i, string j, int[] arr) {
757                 return (arr == null) ? 0 : 1;
758         }
759
760         public static int test_0_marshal_array_delegate_null_blittable () {
761                 return mono_test_marshal_array_delegate1 (null, 0, new ArrayDelegateBlittable (array_delegate_null_blittable));
762         }
763
764         public delegate int ArrayDelegate3 (int i, 
765                                                                                 string j, 
766                                                                                 [In, MarshalAs(UnmanagedType.LPArray, 
767                                                                                                            ArraySubType=UnmanagedType.LPStr, SizeParamIndex=3)] string[] arr);
768
769         [DllImport ("libtest", EntryPoint="mono_test_marshal_array_delegate")]
770         public static extern int mono_test_marshal_array_delegate3 (string[] arr, int len, ArrayDelegate3 d);
771
772         public static int array_delegate3 (int i, string j, string[] arr) {
773                 return (arr == null) ? 0 : 1;
774         }
775
776         public static int test_0_marshal_array_delegate_bad_paramindex () {
777                 try {
778                         mono_test_marshal_array_delegate3 (null, 0, new ArrayDelegate3 (array_delegate3));
779                         return 1;
780                 }
781                 catch (MarshalDirectiveException) {
782                         return 0;
783                 }
784         }
785
786         public delegate int ArrayDelegate4 (int i, 
787                                                                                 string j, 
788                                                                                 [In, MarshalAs(UnmanagedType.LPArray, 
789                                                                                                            ArraySubType=UnmanagedType.LPStr, SizeParamIndex=1)] string[] arr);
790
791         [DllImport ("libtest", EntryPoint="mono_test_marshal_array_delegate")]
792         public static extern int mono_test_marshal_array_delegate4 (string[] arr, int len, ArrayDelegate4 d);
793
794         public static int array_delegate4 (int i, string j, string[] arr) {
795                 return (arr == null) ? 0 : 1;
796         }
797
798         public static int test_0_marshal_array_delegate_bad_paramtype () {
799                 try {
800                         mono_test_marshal_array_delegate4 (null, 0, new ArrayDelegate4 (array_delegate4));
801                         return 1;
802                 }
803                 catch (MarshalDirectiveException) {
804                         return 0;
805                 }
806         }
807
808         public delegate int ArrayDelegate4_2 (int i, 
809                                                                                 string j, 
810                                                                                   string[] arr);
811
812         [DllImport ("libtest", EntryPoint="mono_test_marshal_array_delegate")]
813         public static extern int mono_test_marshal_array_delegate4_2 (string[] arr, int len, ArrayDelegate4_2 d);
814
815         public static int array_delegate4_2 (int i, string j, string[] arr) {
816                 return (arr == null) ? 0 : 1;
817         }
818
819         public static int test_0_marshal_array_delegate_no_marshal_directive () {
820                 try {
821                         mono_test_marshal_array_delegate4_2 (null, 0, new ArrayDelegate4_2 (array_delegate4_2));
822                         return 1;
823                 }
824                 catch (MarshalDirectiveException) {
825                         return 0;
826                 }
827         }
828
829         public delegate int ArrayDelegate4_3 (int i, 
830                                                                                 string j, 
831                                                                                   string[] arr);
832
833         [DllImport ("libtest", EntryPoint="mono_test_marshal_array_delegate")]
834         public static extern int mono_test_marshal_array_delegate4_3 (string[] arr, int len, ArrayDelegate4_3 d);
835
836         public int array_delegate4_3 (int i, string j, string[] arr) {
837                 return (arr == null) ? 0 : 1;
838         }
839
840         public static int test_0_marshal_array_delegate_no_marshal_directive_instance () {
841                 try {
842                         Tests t = new Tests ();
843                         mono_test_marshal_array_delegate4_3 (null, 0, new ArrayDelegate4_3 (t.array_delegate4_3));
844                         return 1;
845                 }
846                 catch (MarshalDirectiveException) {
847                         return 0;
848                 }
849         }
850
851         public delegate int ArrayDelegate5 (int i, 
852                                                                                 string j, 
853                                                                                 [In, MarshalAs(UnmanagedType.LPArray, 
854                                                                                                            ArraySubType=UnmanagedType.LPWStr, SizeParamIndex=0)] string[] arr);
855
856         [DllImport ("libtest", EntryPoint="mono_test_marshal_array_delegate", CharSet=CharSet.Unicode)]
857         public static extern int mono_test_marshal_array_delegate5 (string[] arr, int len, ArrayDelegate5 d);
858
859         public static int array_delegate5 (int i, string j, string[] arr) {
860                 if (arr.Length != 2)
861                         return 1;
862                 if ((arr [0] != "ABC") || (arr [1] != "DEF"))
863                         return 2;
864                 return 0;
865         }
866
867         public static int test_0_marshal_array_delegate_unicode_string () {     
868                 string[] arr = new string [] { "ABC", "DEF" };
869                 return mono_test_marshal_array_delegate5 (arr, arr.Length, new ArrayDelegate5 (array_delegate5));
870         }
871
872         public delegate int ArrayDelegate6 (int i, 
873                                                                                 string j, 
874                                                                                 [In, MarshalAs(UnmanagedType.LPArray, 
875                                                                                                            ArraySubType=UnmanagedType.LPStr, SizeConst=2)] string[] arr);
876
877         [DllImport ("libtest", EntryPoint="mono_test_marshal_array_delegate")]
878         public static extern int mono_test_marshal_array_delegate6 (string[] arr, int len, ArrayDelegate6 d);
879
880         public static int array_delegate6 (int i, string j, string[] arr) {
881                 if (arr.Length != 2)
882                         return 1;
883                 if ((arr [0] != "ABC") || (arr [1] != "DEF"))
884                         return 2;
885                 return 0;
886         }
887
888         public static int test_0_marshal_array_delegate_sizeconst () {  
889                 string[] arr = new string [] { "ABC", "DEF" };
890                 return mono_test_marshal_array_delegate6 (arr, 1024, new ArrayDelegate6 (array_delegate6));
891         }
892
893         public delegate int ArrayDelegate7 (int i, 
894                                                                                 string j, 
895                                                                                 [In, MarshalAs(UnmanagedType.LPArray, 
896                                                                                                            ArraySubType=UnmanagedType.LPStr, SizeConst=1, SizeParamIndex=0)] string[] arr);
897
898         [DllImport ("libtest", EntryPoint="mono_test_marshal_array_delegate")]
899         public static extern int mono_test_marshal_array_delegate7 (string[] arr, int len, ArrayDelegate7 d);
900
901         public static int array_delegate7 (int i, string j, string[] arr) {
902                 if (arr.Length != 2)
903                         return 1;
904                 if ((arr [0] != "ABC") || (arr [1] != "DEF"))
905                         return 2;
906                 return 0;
907         }
908
909         public static int test_0_marshal_array_delegate_sizeconst_paramindex () {       
910                 string[] arr = new string [] { "ABC", "DEF" };
911                 return mono_test_marshal_array_delegate7 (arr, 1, new ArrayDelegate7 (array_delegate7));
912         }
913
914         public delegate int ArrayDelegate8 (int i, string j,
915                                                                                 [In, MarshalAs(UnmanagedType.LPArray, 
916                                                                                 SizeParamIndex=0)] 
917                                                                                 int[] arr);
918
919         [DllImport ("libtest", EntryPoint="mono_test_marshal_array_delegate")]
920         public static extern int mono_test_marshal_array_delegate8 (int[] arr, int len, ArrayDelegate8 d);
921
922         public static int array_delegate8 (int i, string j, int[] arr) {
923                 if (arr.Length != 2)
924                         return 1;
925                 if ((arr [0] != 42) || (arr [1] != 43))
926                         return 2;
927                 return 0;
928         }
929
930         public static int test_0_marshal_array_delegate_blittable () {  
931                 int[] arr = new int [] { 42, 43 };
932                 return mono_test_marshal_array_delegate8 (arr, 2, new ArrayDelegate8 (array_delegate8));
933         }
934
935         /* Array with size param of type long */
936
937         public delegate int ArrayDelegate8_2 (long i, 
938                                                                                 string j, 
939                                                                                 [In, MarshalAs(UnmanagedType.LPArray, 
940                                                                                                            ArraySubType=UnmanagedType.LPStr, SizeParamIndex=0)] string[] arr);
941
942         [DllImport ("libtest", EntryPoint="mono_test_marshal_array_delegate_long")]
943         public static extern int mono_test_marshal_array_delegate8_2 (string[] arr, long len, ArrayDelegate8_2 d);
944
945         public static int array_delegate8_2 (long i, string j, string[] arr) {
946                 if (arr.Length != 2)
947                         return 1;
948                 if ((arr [0] != "ABC") || (arr [1] != "DEF"))
949                         return 2;
950                 return 0;
951         }
952
953         public static int test_0_marshal_array_delegate_long_param () { 
954                 string[] arr = new string [] { "ABC", "DEF" };
955                 return mono_test_marshal_array_delegate8_2 (arr, arr.Length, new ArrayDelegate8_2 (array_delegate8_2));
956         }
957
958
959         /*
960          * [Out] blittable arrays
961          */
962
963         public delegate int ArrayDelegate9 (int i, string j,
964                                                                                 [Out, MarshalAs(UnmanagedType.LPArray, 
965                                                                                 SizeParamIndex=0)] 
966                                                                                 int[] arr);
967
968         [DllImport ("libtest", EntryPoint="mono_test_marshal_out_array_delegate")]
969         public static extern int mono_test_marshal_out_array_delegate (int[] arr, int len, ArrayDelegate9 d);
970
971         public static int array_delegate9 (int i, string j, int[] arr) {
972                 if (arr.Length != 2)
973                         return 1;
974
975                 arr [0] = 1;
976                 arr [1] = 2;
977
978                 return 0;
979         }
980
981         public static int test_0_marshal_out_array_delegate () {        
982                 int[] arr = new int [] { 42, 43 };
983                 return mono_test_marshal_out_array_delegate (arr, 2, new ArrayDelegate9 (array_delegate9));
984         }
985
986         /*
987          * [Out] string arrays
988          */
989
990         public delegate int ArrayDelegate10 (int i, 
991                                                                                  string j, 
992                                                                                  [Out, MarshalAs(UnmanagedType.LPArray, 
993                                                                                                                  ArraySubType=UnmanagedType.LPStr, SizeConst=2)] string[] arr);
994
995         [DllImport ("libtest", EntryPoint="mono_test_marshal_out_string_array_delegate")]
996         public static extern int mono_test_marshal_out_string_array_delegate (string[] arr, int len, ArrayDelegate10 d);
997
998         public static int array_delegate10 (int i, string j, string[] arr) {
999                 if (arr.Length != 2)
1000                         return 1;
1001
1002                 arr [0] = "ABC";
1003                 arr [1] = "DEF";
1004
1005                 return 0;
1006         }
1007
1008         public static int test_0_marshal_out_string_array_delegate () { 
1009                 string[] arr = new string [] { "", "" };
1010                 return mono_test_marshal_out_string_array_delegate (arr, 2, new ArrayDelegate10 (array_delegate10));
1011         }
1012
1013         /*
1014          * [In, Out] classes
1015          */
1016
1017         public delegate int InOutByvalClassDelegate ([In, Out] SimpleClass ss);
1018
1019         [DllImport ("libtest", EntryPoint="mono_test_marshal_inout_byval_class_delegate")]
1020         public static extern int mono_test_marshal_inout_byval_class_delegate (InOutByvalClassDelegate d);
1021
1022         public static int delegate_test_byval_class_inout (SimpleClass ss) {
1023                 if ((ss.a != false) || (ss.b != true) || (ss.c != false) || (ss.d != "FOO"))
1024                         return 1;
1025
1026                 ss.a = true;
1027                 ss.b = false;
1028                 ss.c = true;
1029                 ss.d = "RES";
1030
1031                 return 0;
1032         }
1033
1034         public static int test_0_marshal_inout_byval_class_delegate () {
1035                 return mono_test_marshal_inout_byval_class_delegate (new InOutByvalClassDelegate (delegate_test_byval_class_inout));
1036         }
1037
1038         /*
1039          * Returning unicode strings
1040          */
1041         [return: MarshalAs(UnmanagedType.LPWStr)]
1042         public delegate string ReturnUnicodeStringDelegate([MarshalAs(UnmanagedType.LPWStr)] string message);
1043
1044         [DllImport ("libtest", EntryPoint="mono_test_marshal_return_unicode_string_delegate")]
1045         public static extern int mono_test_marshal_return_unicode_string_delegate (ReturnUnicodeStringDelegate d);
1046
1047         public static String return_unicode_string_delegate (string message) {
1048                 return message;
1049         }
1050
1051         public static int test_0_marshal_return_unicode_string_delegate () {    
1052                 return mono_test_marshal_return_unicode_string_delegate (new ReturnUnicodeStringDelegate (return_unicode_string_delegate));
1053         }
1054
1055         /*
1056          * Returning string arrays
1057          */
1058         public delegate string[] ReturnArrayDelegate (int i);
1059
1060         [DllImport ("libtest", EntryPoint="mono_test_marshal_return_string_array_delegate")]
1061         public static extern int mono_test_marshal_return_string_array_delegate (ReturnArrayDelegate d);
1062
1063         public static String[] return_array_delegate (int i) {
1064                 String[] arr = new String [2];
1065
1066                 arr [0] = "ABC";
1067                 arr [1] = "DEF";
1068
1069                 return arr;
1070         }
1071
1072         public static String[] return_array_delegate_null (int i) {
1073                 return null;
1074         }
1075
1076         public static int test_0_marshal_return_string_array_delegate () {      
1077                 return mono_test_marshal_return_string_array_delegate (new ReturnArrayDelegate (return_array_delegate));
1078         }
1079
1080         public static int test_3_marshal_return_string_array_delegate_null () { 
1081                 return mono_test_marshal_return_string_array_delegate (new ReturnArrayDelegate (return_array_delegate_null));
1082         }
1083
1084         /*
1085          * Byref string marshalling
1086          */
1087         public delegate int ByrefStringDelegate (ref string s);
1088
1089         [DllImport ("libtest", EntryPoint="mono_test_marshal_byref_string_delegate")]
1090         public static extern int mono_test_marshal_byref_string_delegate (ByrefStringDelegate d);
1091
1092         public static int byref_string_delegate (ref string s) {
1093                 if (s != "ABC")
1094                         return 1;
1095
1096                 s = "DEF";
1097
1098                 return 0;
1099         }
1100
1101         public static int test_0_marshal_byref_string_delegate () {     
1102                 return mono_test_marshal_byref_string_delegate (new ByrefStringDelegate (byref_string_delegate));
1103         }
1104
1105         /*
1106          * Thread attach
1107          */
1108
1109         public delegate int SimpleDelegate (int i);
1110
1111         [DllImport ("libtest", EntryPoint="mono_test_marshal_thread_attach")]
1112         public static extern int mono_test_marshal_thread_attach (SimpleDelegate d);
1113
1114         public static int test_43_thread_attach () {
1115                 int res = mono_test_marshal_thread_attach (delegate (int i) {
1116                                 if (!Thread.CurrentThread.IsBackground)
1117                                         return 0;
1118                                 return i + 1;
1119                         });
1120                 return res;
1121         }
1122
1123         public struct LargeStruct {
1124             public Int16 s;
1125             public Int16 v;
1126             public UInt32 p;
1127             public UInt32 e;
1128             public Int32 l;
1129             public Int32 ll;
1130             public UInt16 h;
1131             public Int16 r;
1132             public Int16 pp;
1133             public Int32 hh;
1134             public Int32 bn;
1135             public Int32 dn;
1136             public Int32 dr;
1137             public Int32 sh;
1138             public Int32 ra;
1139             [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
1140             public Int32[] angle;
1141             [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
1142             public Int32[] width;
1143             [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
1144             public Int32[] edge;
1145             [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3 * 1024)]
1146             public byte[] echo;
1147         }
1148
1149         public delegate int LargeStructDelegate (ref LargeStruct s);
1150
1151         [DllImport ("libtest", EntryPoint="mono_test_marshal_thread_attach_large_vt")]
1152         public static extern int mono_test_marshal_thread_attach_large_vt (LargeStructDelegate d);
1153
1154         public static int test_43_thread_attach_large_vt () {
1155                 int res = mono_test_marshal_thread_attach_large_vt (delegate (ref LargeStruct s) {
1156                                 return 43;
1157                         });
1158                 return res;
1159         }
1160
1161         class Worker {
1162                 volatile bool stop = false;
1163                 public void Stop () {
1164                         stop = true;
1165                 }
1166
1167                 public void Work () {
1168                         while (!stop) {
1169                                 for (int i = 0; i < 100; i++) {
1170                                         var a = new double[80000];
1171                                         Thread.Sleep (0);
1172                                 }
1173                                 GC.Collect ();
1174                         }
1175                 }
1176         }
1177
1178         public static int test_43_thread_attach_detach_contested () {
1179                 // Test plan: we want to create a race between the GC
1180                 // and native threads detaching.  When a native thread
1181                 // calls a managed delegate, it's attached to the
1182                 // runtime by the wrapper.  It is detached when the
1183                 // thread is destroyed and the TLS key destructor for
1184                 // MonoThreadInfo runs.  That destructor wants to take
1185                 // the GC lock.  So we create a lot of native threads
1186                 // while at the same time running a worker that
1187                 // allocates garbage and invokes the collector.
1188                 var w = new Worker ();
1189                 Thread t = new Thread(new ThreadStart (w.Work));
1190                 t.Start ();
1191
1192                 for (int count = 0; count < 500; count++) {
1193                         int res = mono_test_marshal_thread_attach (delegate (int i) {
1194                                         Thread.Sleep (0);
1195                                         return i + 1;
1196                                 });
1197                 }
1198                 Thread.Sleep (1000);
1199                 w.Stop ();
1200                 t.Join ();
1201                 return 43; 
1202
1203         }
1204         /*
1205          * Appdomain save/restore
1206          */
1207     static Func<int> callback;
1208
1209         [DllImport ("libtest", EntryPoint="mono_test_marshal_set_callback")]
1210         public static extern int mono_test_marshal_set_callback (Func<int> a);
1211
1212         [DllImport ("libtest", EntryPoint="mono_test_marshal_call_callback")]
1213         public static extern int mono_test_marshal_call_callback ();
1214
1215         public static int test_0_appdomain_switch () {
1216                 // FIXME: The appdomain unload hangs
1217                 //return 0;
1218         AppDomain ad = AppDomain.CreateDomain ("foo");
1219                 var c = (CallbackClass)ad.CreateInstanceAndUnwrap (
1220                                 typeof (CallbackClass).Assembly.FullName, "Tests/CallbackClass");
1221                 c.SetCallback ();
1222                 int domain_id = AppDomain.CurrentDomain.Id;
1223                 int new_id = mono_test_marshal_call_callback ();
1224                 int res = 0;
1225                 if (new_id == domain_id)
1226                         res = 1;
1227                 if (AppDomain.CurrentDomain.Id != domain_id)
1228                         res = 2;
1229                 AppDomain.Unload (ad);
1230                 return res;
1231     }
1232
1233         static int domain_callback () {
1234                 return AppDomain.CurrentDomain.Id;
1235         }
1236
1237         class CallbackClass : MarshalByRefObject {
1238                 public int SetCallback () {
1239                         mono_test_marshal_set_callback (domain_callback);
1240                         return 0;
1241                 }
1242     }
1243
1244         class Base {
1245                 public VirtualDelegate get_del () {
1246                         return delegate_test;
1247                 }
1248
1249                 public virtual int delegate_test (int i) {
1250                         return i;
1251                 }
1252         }
1253
1254         class Derived : Base {
1255                 public override int delegate_test (int i) {
1256                         return i + 1;
1257                 }
1258         }
1259
1260         public static int test_43_virtual () {
1261                 Base b = new Derived ();
1262
1263                 return mono_test_marshal_virtual_delegate (b.get_del ());
1264         }
1265
1266         public static int test_0_icall_delegate () {
1267                 var m = typeof (Marshal).GetMethod ("PtrToStringAnsi", new Type[] { typeof (IntPtr) });
1268
1269                 return mono_test_marshal_icall_delegate ((IcallDelegate)Delegate.CreateDelegate (typeof (IcallDelegate), m));
1270         }
1271 }