Merge pull request #1218 from AndreyAkinshin/master
[mono.git] / mono / tests / pinvoke2.cs
1 //
2 // Copyright 2011 Xamarin Inc (http://www.xamarin.com).
3 //
4
5 using System;
6 using System.Text;
7 using System.Runtime.InteropServices;
8 using System.Runtime.CompilerServices;
9 using System.Reflection.Emit;
10
11 public class Tests {
12
13         public int int_field;
14
15         public static int delegate_test (int a)
16         {
17                 if (a == 2)
18                         return 0;
19
20                 return 1;
21         }
22
23         public int delegate_test_instance (int a)
24         {
25                 return int_field + a;
26         }
27         
28         [StructLayout (LayoutKind.Sequential)]
29         public struct SimpleStruct {
30                 public bool a;
31                 public bool b;
32                 public bool c;
33                 public string d;
34                 [MarshalAs(UnmanagedType.LPWStr)]
35                 public string d2;
36         }
37
38         [StructLayout (LayoutKind.Sequential)]
39         public struct SimpleStructGen<T> {
40                 public bool a;
41                 public bool b;
42                 public bool c;
43                 public string d;
44                 [MarshalAs(UnmanagedType.LPWStr)]
45                 public string d2;
46         }
47
48         [StructLayout (LayoutKind.Sequential)]
49         public struct SimpleStruct2 {
50                 public bool a;
51                 public bool b;
52                 public bool c;
53                 public string d;
54                 public byte e;
55                 public double f;
56                 public byte g;
57                 public long h;
58         }
59
60         [StructLayout (LayoutKind.Sequential, Size=0)]
61         public struct EmptyStruct {
62         }
63
64         [StructLayout (LayoutKind.Sequential, Size=1)]
65         public struct EmptyStructCpp {
66         }
67
68         [StructLayout (LayoutKind.Sequential)]
69         public struct DelegateStruct {
70                 public int a;
71                 public SimpleDelegate del;
72                 [MarshalAs(UnmanagedType.FunctionPtr)] 
73                 public SimpleDelegate del2;
74                 [MarshalAs(UnmanagedType.FunctionPtr)] 
75                 public SimpleDelegate del3;
76         }
77
78         [StructLayout (LayoutKind.Sequential)]
79         public struct SingleDoubleStruct {
80                 public double d;
81         }
82
83         /* sparcv9 has complex conventions when passing structs with doubles in them 
84            by value, some simple tests for them */
85         [StructLayout (LayoutKind.Sequential)]
86         public struct Point {
87                 public double x;
88                 public double y;
89         }
90
91         [StructLayout (LayoutKind.Sequential)]
92         public struct MixedPoint {
93                 public int x;
94                 public double y;
95         }
96         
97         [StructLayout (LayoutKind.Sequential)]
98         public struct TinyStruct {
99                 public TinyStruct (int i)
100                 {
101                         this.i = i;
102                 }
103                 public int i;
104         }
105
106         [StructLayout (LayoutKind.Sequential)]
107         public class SimpleClass {
108                 public bool a;
109                 public bool b;
110                 public bool c;
111                 public string d;
112                 public byte e;
113                 public double f;
114                 public byte g;
115                 public long h;
116         }
117
118         [StructLayout (LayoutKind.Sequential)]
119         public class EmptyClass {
120         }
121
122         [StructLayout (LayoutKind.Sequential)]
123         public struct LongAlignStruct {
124                 public int a;
125                 public long b;
126                 public long c;
127         }
128
129         [StructLayout(LayoutKind.Sequential)]
130         public class BlittableClass
131         {
132                 public int a = 1;
133                 public int b = 2;
134         }
135
136         [StructLayout (LayoutKind.Sequential)]
137         class SimpleObj
138         {
139                 public string str;
140                 public int i;
141         }
142
143         [StructLayout(LayoutKind.Sequential)]
144         struct AsAnyStruct
145         {
146                 public int i;
147                 public int j;
148                 public int k;
149                 public String s;
150
151                 public AsAnyStruct(int i, int j, int k, String s) {
152                         this.i = i;
153                         this.j = j;
154                         this.k = k;
155                         this.s = s;
156                 }
157         }
158
159         [StructLayout(LayoutKind.Sequential)]
160         class AsAnyClass
161         {
162                 public int i;
163                 public int j;
164                 public int k;
165                 public String s;
166
167                 public AsAnyClass(int i, int j, int k, String s) {
168                         this.i = i;
169                         this.j = j;
170                         this.k = k;
171                 }
172         }
173
174         [DllImport ("libnot-found", EntryPoint="not_found")]
175         public static extern int mono_library_not_found ();
176
177         [DllImport ("libtest", EntryPoint="not_found")]
178         public static extern int mono_entry_point_not_found ();
179
180         [DllImport ("libtest.dll", EntryPoint="mono_test_marshal_char")]
181         public static extern int mono_test_marshal_char_2 (char a1);
182
183         [DllImport ("test", EntryPoint="mono_test_marshal_char")]
184         public static extern int mono_test_marshal_char_3 (char a1);
185
186         [DllImport ("libtest", EntryPoint="mono_test_marshal_char")]
187         public static extern int mono_test_marshal_char (char a1);
188
189         [DllImport ("libtest", EntryPoint="mono_test_marshal_char_array", CharSet=CharSet.Unicode)]
190         public static extern int mono_test_marshal_char_array (char[] a1);
191
192         [DllImport ("libtest", EntryPoint="mono_test_marshal_bool_byref")]
193         public static extern int mono_test_marshal_bool_byref (int a, ref bool b, int c);
194
195         [DllImport ("libtest", EntryPoint="mono_test_marshal_bool_in_as_I1_U1")]
196         public static extern int mono_test_marshal_bool_in_as_I1 ([MarshalAs (UnmanagedType.I1)] bool bTrue, [MarshalAs (UnmanagedType.I1)] bool bFalse);
197
198         [DllImport ("libtest", EntryPoint="mono_test_marshal_bool_in_as_I1_U1")]
199         public static extern int mono_test_marshal_bool_in_as_U1 ([MarshalAs (UnmanagedType.U1)] bool bTrue, [MarshalAs (UnmanagedType.U1)] bool bFalse);
200
201         [DllImport ("libtest", EntryPoint="mono_test_marshal_bool_out_as_I1_U1")]
202         public static extern int mono_test_marshal_bool_out_as_I1 ([MarshalAs (UnmanagedType.I1)] out bool bTrue, [MarshalAs (UnmanagedType.I1)] out bool bFalse);
203
204         [DllImport ("libtest", EntryPoint="mono_test_marshal_bool_out_as_I1_U1")]
205         public static extern int mono_test_marshal_bool_out_as_U1 ([MarshalAs (UnmanagedType.U1)] out bool bTrue, [MarshalAs (UnmanagedType.U1)] out bool bFalse);
206
207         [DllImport ("libtest", EntryPoint="mono_test_marshal_bool_ref_as_I1_U1")]
208         public static extern int mono_test_marshal_bool_ref_as_I1 ([MarshalAs (UnmanagedType.I1)] ref bool bTrue, [MarshalAs (UnmanagedType.I1)] ref bool bFalse);
209
210         [DllImport ("libtest", EntryPoint="mono_test_marshal_bool_ref_as_I1_U1")]
211         public static extern int mono_test_marshal_bool_ref_as_U1 ([MarshalAs (UnmanagedType.U1)] ref bool bTrue, [MarshalAs (UnmanagedType.U1)] ref bool bFalse);
212
213         [DllImport ("libtest", EntryPoint="mono_test_marshal_array")]
214         public static extern int mono_test_marshal_array (int [] a1);
215
216         [DllImport ("libtest", EntryPoint="mono_test_marshal_empty_string_array")]
217         public static extern int mono_test_marshal_empty_string_array (string [] a1);
218
219         [DllImport ("libtest", EntryPoint="mono_test_marshal_string_array")]
220         public static extern int mono_test_marshal_string_array (string [] a1);
221
222         [DllImport ("libtest", EntryPoint="mono_test_marshal_unicode_string_array", CharSet=CharSet.Unicode)]
223         public static extern int mono_test_marshal_unicode_string_array (string [] a1, [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStr)]string [] a2);
224
225         [DllImport ("libtest", EntryPoint="mono_test_marshal_stringbuilder_array")]
226         public static extern int mono_test_marshal_stringbuilder_array (StringBuilder [] a1);   
227
228         [DllImport ("libtest", EntryPoint="mono_test_marshal_inout_array")]
229         public static extern int mono_test_marshal_inout_array ([In, Out] int [] a1);
230
231         [DllImport ("libtest", EntryPoint="mono_test_marshal_out_array")]
232         public static extern int mono_test_marshal_out_array ([Out] [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] int [] a1, int n);
233
234         [DllImport ("libtest", EntryPoint="mono_test_marshal_out_byref_array_out_size_param")]
235         public static extern int mono_test_marshal_out_byref_array_out_size_param ([Out] [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] out int [] a1, out int n);
236
237         [DllImport ("libtest", EntryPoint="mono_test_marshal_inout_nonblittable_array", CharSet = CharSet.Unicode)]
238         public static extern int mono_test_marshal_inout_nonblittable_array ([In, Out] char [] a1);
239         
240         [DllImport ("libtest", EntryPoint="mono_test_marshal_struct")]
241         public static extern int mono_test_marshal_struct (SimpleStruct ss);
242         
243         [DllImport ("libtest", EntryPoint="mono_test_marshal_struct")]
244         public static extern int mono_test_marshal_struct_gen (SimpleStructGen<string> ss);
245
246         [DllImport ("libtest", EntryPoint="mono_test_marshal_struct2")]
247         public static extern int mono_test_marshal_struct2 (SimpleStruct2 ss);
248
249         [DllImport ("libtest", EntryPoint="mono_test_marshal_struct2_2")]
250         public static extern int mono_test_marshal_struct2_2 (int i, int j, int k, SimpleStruct2 ss);
251
252         [DllImport ("libtest", EntryPoint="mono_test_marshal_byref_struct")]
253         public static extern int mono_test_marshal_byref_struct (ref SimpleStruct ss, bool a, bool b, bool c, String d);
254
255         [DllImport ("libtest", EntryPoint="mono_test_marshal_byref_struct")]
256         public static extern int mono_test_marshal_byref_struct_in ([In] ref SimpleStruct ss, bool a, bool b, bool c, String d);
257
258         [DllImport ("libtest", EntryPoint="mono_test_marshal_byref_struct")]
259         public static extern int mono_test_marshal_byref_struct_inout ([In, Out] ref SimpleStruct ss, bool a, bool b, bool c, String d);
260
261         [DllImport ("libtest", EntryPoint="mono_test_marshal_point")]
262         public static extern int mono_test_marshal_point (Point p);
263
264         [DllImport ("libtest", EntryPoint="mono_test_marshal_mixed_point")]
265         public static extern int mono_test_marshal_mixed_point (MixedPoint p);
266
267         [DllImport ("libtest", EntryPoint="mono_test_empty_struct")]
268         public static extern int mono_test_empty_struct (int a, EmptyStruct es, int b);
269
270         [DllImport ("libtest", EntryPoint="mono_test_return_empty_struct")]
271         public static extern EmptyStruct mono_test_return_empty_struct (int a);
272
273         [DllImport ("libtest", EntryPoint="mono_test_return_empty_struct")]
274         public static extern EmptyStructCpp mono_test_return_empty_struct_cpp (int a);
275
276         [DllImport ("libtest", EntryPoint="mono_test_marshal_lpstruct")]
277         public static extern int mono_test_marshal_lpstruct ([In, MarshalAs(UnmanagedType.LPStruct)] SimpleStruct ss);
278
279         [DllImport ("libtest", EntryPoint="mono_test_marshal_lpstruct_blittable")]
280         public static extern int mono_test_marshal_lpstruct_blittable ([In, MarshalAs(UnmanagedType.LPStruct)] Point p);
281
282         [DllImport ("libtest", EntryPoint="mono_test_marshal_struct_array")]
283         public static extern int mono_test_marshal_struct_array (SimpleStruct2[] ss);
284
285         [DllImport ("libtest", EntryPoint="mono_test_marshal_long_align_struct_array")]
286         public static extern int mono_test_marshal_long_align_struct_array (LongAlignStruct[] ss);
287
288         [DllImport ("libtest", EntryPoint="mono_test_marshal_class")]
289         public static extern SimpleClass mono_test_marshal_class (int i, int j, int k, SimpleClass ss, int l);
290
291         [DllImport ("libtest", EntryPoint="mono_test_marshal_byref_class")]
292         public static extern int mono_test_marshal_byref_class (ref SimpleClass ss);
293
294         [DllImport ("libtest", EntryPoint="mono_test_marshal_delegate")]
295         public static extern int mono_test_marshal_delegate (SimpleDelegate d);
296
297         [DllImport ("libtest", EntryPoint="mono_test_marshal_delegate_struct")]
298         public static extern DelegateStruct mono_test_marshal_delegate_struct (DelegateStruct d);
299
300         [DllImport ("libtest", EntryPoint="mono_test_marshal_return_delegate")]
301         public static extern SimpleDelegate mono_test_marshal_return_delegate (SimpleDelegate d);
302
303         [DllImport ("libtest", EntryPoint="mono_test_return_vtype")]
304         public static extern SimpleStruct mono_test_return_vtype (IntPtr i);
305
306         [DllImport ("libtest", EntryPoint="mono_test_marshal_stringbuilder")]
307         public static extern void mono_test_marshal_stringbuilder (StringBuilder sb, int len);
308
309         [DllImport ("libtest", EntryPoint="mono_test_marshal_stringbuilder_default")]
310         public static extern void mono_test_marshal_stringbuilder_default (StringBuilder sb, int len);
311
312         [DllImport ("libtest", EntryPoint="mono_test_marshal_stringbuilder_append")]
313         public static extern void mono_test_marshal_stringbuilder_append (StringBuilder sb, int len);
314
315         [DllImport ("libtest", EntryPoint="mono_test_marshal_stringbuilder_unicode", CharSet=CharSet.Unicode)]
316         public static extern void mono_test_marshal_stringbuilder_unicode (StringBuilder sb, int len);
317
318         [DllImport ("libtest", EntryPoint="mono_test_marshal_stringbuilder_out")]
319         public static extern void mono_test_marshal_stringbuilder_out (out StringBuilder sb);
320
321         [DllImport ("libtest", EntryPoint="mono_test_marshal_stringbuilder_ref")]
322         public static extern int mono_test_marshal_stringbuilder_ref (ref StringBuilder sb);
323
324         [DllImport ("libtest", EntryPoint="mono_test_marshal_stringbuilder_out_unicode", CharSet=CharSet.Unicode)]
325         public static extern void mono_test_marshal_stringbuilder_out_unicode (out StringBuilder sb);
326
327         [DllImport ("libtest", EntryPoint="mono_test_last_error", SetLastError=true)]
328         public static extern void mono_test_last_error (int err);
329
330         [DllImport ("libtest", EntryPoint="mono_test_asany")]
331         public static extern int mono_test_asany ([MarshalAs (UnmanagedType.AsAny)] object o, int what);
332
333         [DllImport ("libtest", EntryPoint="mono_test_asany", CharSet=CharSet.Unicode)]
334         public static extern int mono_test_asany_unicode ([MarshalAs (UnmanagedType.AsAny)] object o, int what);
335
336         [DllImport("libtest", EntryPoint="mono_test_marshal_asany_in")]
337         static extern void mono_test_asany_in ([MarshalAs(UnmanagedType.AsAny)][In] object obj); 
338
339         [DllImport("libtest", EntryPoint="mono_test_marshal_asany_out")]
340         static extern void mono_test_asany_out ([MarshalAs(UnmanagedType.AsAny)][Out] object obj); 
341         [DllImport("libtest", EntryPoint="mono_test_marshal_asany_inout")]
342         static extern void mono_test_asany_inout ([MarshalAs(UnmanagedType.AsAny)][In, Out] object obj); 
343
344         [DllImport ("libtest")]
345         static extern int class_marshal_test0 (SimpleObj obj);
346
347         [DllImport ("libtest")]
348         static extern void class_marshal_test1 (out SimpleObj obj);
349
350         [DllImport ("libtest")]
351         static extern int class_marshal_test4 (SimpleObj obj);
352         
353         [DllImport ("libtest")]
354         static extern int string_marshal_test0 (string str);
355
356         [DllImport ("libtest")]
357         static extern void string_marshal_test1 (out string str);
358
359         [DllImport ("libtest")]
360         static extern int string_marshal_test2 (ref string str);
361
362         [DllImport ("libtest")]
363         static extern int string_marshal_test3 (string str);
364
365         public delegate int SimpleDelegate (int a);
366
367         public static int Main (string[] args) {
368                 return TestDriver.RunTests (typeof (Tests), args);
369         }
370
371         public static int test_0_marshal_char () {
372                 return mono_test_marshal_char ('a');
373         }
374
375         public static int test_0_marshal_char_array () {
376                 // a unicode char[] is implicitly marshalled as [Out]
377                 char[] buf = new char [32];
378                 mono_test_marshal_char_array (buf);
379                 string s = new string (buf);
380                 if (s.StartsWith ("abcdef"))
381                         return 0;
382                 else
383                         return 1;
384         }
385
386         public static int test_1225_marshal_array () {
387                 int [] a1 = new int [50];
388                 for (int i = 0; i < 50; i++)
389                         a1 [i] = i;
390
391                 return mono_test_marshal_array (a1);
392         }
393
394         public static int test_1225_marshal_inout_array () {
395                 int [] a1 = new int [50];
396                 for (int i = 0; i < 50; i++)
397                         a1 [i] = i;
398
399                 int res = mono_test_marshal_inout_array (a1);
400
401                 for (int i = 0; i < 50; i++)
402                         if (a1 [i] != 50 - i) {
403                                 Console.WriteLine ("X: " + i + " " + a1 [i]);
404                                 return 2;
405                         }
406
407                 return res;
408         }
409
410         public static int test_0_marshal_out_array () {
411                 int [] a1 = new int [50];
412
413                 int res = mono_test_marshal_out_array (a1, 0);
414
415                 for (int i = 0; i < 50; i++)
416                         if (a1 [i] != i) {
417                                 Console.WriteLine ("X: " + i + " " + a1 [i]);
418                                 return 2;
419                         }
420
421                 return 0;
422         }
423
424         public static int test_0_marshal_out_byref_array_out_size_param () {
425                 int [] a1 = null;
426                 int len;
427
428                 int res = mono_test_marshal_out_byref_array_out_size_param (out a1, out len);
429                 if (len != 4)
430                         return 1;
431                 for (int i = 0; i < len; i++)
432                         if (a1 [i] != i)
433                                 return 2;
434                 return 0;
435         }
436
437         public static int test_0_marshal_inout_nonblittable_array () {
438                 char [] a1 = new char [10];
439                 for (int i = 0; i < 10; i++)
440                         a1 [i] = "Hello, World" [i];
441
442                 int res = mono_test_marshal_inout_nonblittable_array (a1);
443
444                 for (int i = 0; i < 10; i++)
445                         if (a1 [i] != 'F')
446                                 return 2;
447
448                 return res;
449         }
450
451         public static int test_0_marshal_struct () {
452                 SimpleStruct ss = new  SimpleStruct ();
453                 ss.b = true;
454                 ss.d = "TEST";
455                 
456                 return mono_test_marshal_struct (ss);
457         }
458
459         public static int test_0_marshal_struct_gen () {
460                 SimpleStructGen<string> ss = new  SimpleStructGen<string> ();
461                 ss.b = true;
462                 ss.d = "TEST";
463                 
464                 return mono_test_marshal_struct_gen (ss);
465         }
466
467         public static int test_0_marshal_struct2 () {
468                 SimpleStruct2 ss2 = new  SimpleStruct2 ();
469                 ss2.b = true;
470                 ss2.d = "TEST";
471                 ss2.e = 99;
472                 ss2.f = 1.5;
473                 ss2.g = 42;
474                 ss2.h = 123L;
475
476                 return mono_test_marshal_struct2 (ss2);
477         }
478
479         public static int test_0_marshal_struct3 () {
480                 SimpleStruct2 ss2 = new  SimpleStruct2 ();
481                 ss2.b = true;
482                 ss2.d = "TEST";
483                 ss2.e = 99;
484                 ss2.f = 1.5;
485                 ss2.g = 42;
486                 ss2.h = 123L;
487
488                 return mono_test_marshal_struct2_2 (10, 11, 12, ss2);
489         }
490
491         public static int test_0_marshal_empty_struct () {
492                 EmptyStruct es = new EmptyStruct ();
493
494                 if (mono_test_empty_struct (1, es, 2) != 0)
495                         return 1;
496
497                 mono_test_return_empty_struct (42);
498
499                 return 0;
500         }
501
502         /* FIXME: This doesn't work on all platforms */
503         /*
504         public static int test_0_marshal_empty_struct_cpp () {
505                 EmptyStructCpp es = new EmptyStructCpp ();
506
507                 mono_test_return_empty_struct_cpp (42);
508                 
509                 return 0;
510         }
511         */
512
513         public static int test_0_marshal_lpstruct () {
514                 SimpleStruct ss = new  SimpleStruct ();
515                 ss.b = true;
516                 ss.d = "TEST";
517                 
518                 return mono_test_marshal_lpstruct (ss);
519         }
520
521         public static int test_0_marshal_lpstruct_blittable () {
522                 Point p = new Point ();
523                 p.x = 1.0;
524                 p.y = 2.0;
525                 
526                 return mono_test_marshal_lpstruct_blittable (p);
527         }
528
529         public static int test_0_marshal_struct_array () {
530                 SimpleStruct2[] ss_arr = new SimpleStruct2 [2];
531
532                 SimpleStruct2 ss2 = new SimpleStruct2 ();
533                 ss2.b = true;
534                 ss2.d = "TEST";
535                 ss2.e = 99;
536                 ss2.f = 1.5;
537                 ss2.g = 42;
538                 ss2.h = 123L;
539
540                 ss_arr [0] = ss2;
541
542                 ss2.b = false;
543                 ss2.d = "TEST2";
544                 ss2.e = 100;
545                 ss2.f = 2.5;
546                 ss2.g = 43;
547                 ss2.h = 124L;
548
549                 ss_arr [1] = ss2;
550
551                 return mono_test_marshal_struct_array (ss_arr);
552         }
553
554         public static int test_105_marshal_long_align_struct_array () {
555                 LongAlignStruct[] ss_arr = new LongAlignStruct [2];
556
557                 LongAlignStruct ss = new LongAlignStruct ();
558                 ss.a = 5;
559                 ss.b = 10;
560                 ss.c = 15;
561
562                 ss_arr [0] = ss;
563
564                 ss.a = 20;
565                 ss.b = 25;
566                 ss.c = 30;
567
568                 ss_arr [1] = ss;
569
570                 return mono_test_marshal_long_align_struct_array (ss_arr);
571         }
572
573         /* Test classes as arguments and return values */
574         public static int test_0_marshal_class () {
575                 SimpleClass ss = new  SimpleClass ();
576                 ss.b = true;
577                 ss.d = "TEST";
578                 ss.e = 99;
579                 ss.f = 1.5;
580                 ss.g = 42;
581                 ss.h = 123L;
582
583                 SimpleClass res = mono_test_marshal_class (10, 11, 12, ss, 14);
584                 if (res == null)
585                         return 1;
586                 if  (! (res.a == ss.a && res.b == ss.b && res.c == ss.c && 
587                                 res.d == ss.d && res.e == ss.e && res.f == ss.f &&
588                                 res.g == ss.g && res.h == ss.h))
589                         return 2;
590
591                 /* Test null arguments and results */
592                 res = mono_test_marshal_class (10, 11, 12, null, 14);
593                 if (res != null)
594                         return 3;
595
596                 return 0;
597         }
598
599         public static int test_0_marshal_byref_class () {
600                 SimpleClass ss = new  SimpleClass ();
601                 ss.b = true;
602                 ss.d = "TEST";
603                 ss.e = 99;
604                 ss.f = 1.5;
605                 ss.g = 42;
606                 ss.h = 123L;
607
608                 int res = mono_test_marshal_byref_class (ref ss);
609                 if (ss.d != "TEST-RES")
610                         return 1;
611
612                 return 0;
613         }
614
615         public static int test_0_marshal_delegate () {
616                 SimpleDelegate d = new SimpleDelegate (delegate_test);
617
618                 return mono_test_marshal_delegate (d);
619         }
620
621         public static int test_34_marshal_instance_delegate () {
622                 Tests t = new Tests ();
623                 t.int_field = 32;
624                 SimpleDelegate d = new SimpleDelegate (t.delegate_test_instance);
625
626                 return mono_test_marshal_delegate (d);
627         }
628
629         /* Static delegates closed over their first argument */
630         public static int closed_delegate (Tests t, int a) {
631                 return t.int_field + a;
632         }
633
634         public static int test_34_marshal_closed_static_delegate () {
635                 Tests t = new Tests ();
636                 t.int_field = 32;
637                 SimpleDelegate d = (SimpleDelegate)Delegate.CreateDelegate (typeof (SimpleDelegate), t, typeof (Tests).GetMethod ("closed_delegate"));
638
639                 return mono_test_marshal_delegate (d);
640         }
641
642         public static int test_0_marshal_return_delegate () {
643                 SimpleDelegate d = new SimpleDelegate (delegate_test);
644
645                 SimpleDelegate d2 = mono_test_marshal_return_delegate (d);
646
647                 return d2 (2);
648         }
649
650         public static int test_0_marshal_delegate_struct () {
651                 DelegateStruct s = new DelegateStruct ();
652
653                 s.a = 2;
654                 s.del = new SimpleDelegate (delegate_test);
655                 s.del2 = new SimpleDelegate (delegate_test);
656                 s.del3 = null;
657
658                 DelegateStruct res = mono_test_marshal_delegate_struct (s);
659
660                 if (res.a != 0)
661                         return 1;
662                 if (res.del (2) != 0)
663                         return 2;
664                 if (res.del2 (2) != 0)
665                         return 3;
666                 if (res.del3 != null)
667                         return 4;
668
669                 return 0;
670         }
671
672         [DllImport ("libtest", EntryPoint="mono_test_marshal_out_delegate")]
673         public static extern int mono_test_marshal_out_delegate (out SimpleDelegate d);
674
675         public static int test_3_marshal_out_delegate () {
676                 SimpleDelegate d = null;
677
678                 mono_test_marshal_out_delegate (out d);
679
680                 return d (2);
681         }
682
683         public static int test_0_marshal_byref_struct () {
684                 SimpleStruct s = new SimpleStruct ();
685                 s.a = true;
686                 s.b = false;
687                 s.c = true;
688                 s.d = "ABC";
689                 s.d2 = "DEF";
690
691                 int res = mono_test_marshal_byref_struct (ref s, true, false, true, "ABC");
692                 if (res != 0)
693                         return 1;
694                 if (s.a != false || s.b != true || s.c != false || s.d != "DEF")
695                         return 2;
696                 return 0;
697         }
698
699         public static int test_0_marshal_byref_struct_in () {
700                 SimpleStruct s = new SimpleStruct ();
701                 s.a = true;
702                 s.b = false;
703                 s.c = true;
704                 s.d = "ABC";
705                 s.d2 = "DEF";
706
707                 int res = mono_test_marshal_byref_struct_in (ref s, true, false, true, "ABC");
708                 if (res != 0)
709                         return 1;
710                 if (s.a != true || s.b != false || s.c != true || s.d != "ABC")
711                         return 2;
712                 return 0;
713         }
714
715         public static int test_0_marshal_byref_struct_inout () {
716                 SimpleStruct s = new SimpleStruct ();
717                 s.a = true;
718                 s.b = false;
719                 s.c = true;
720                 s.d = "ABC";
721                 s.d2 = "DEF";
722
723                 int res = mono_test_marshal_byref_struct_inout (ref s, true, false, true, "ABC");
724                 if (res != 0)
725                         return 1;
726                 if (s.a != false || s.b != true || s.c != false || s.d != "DEF")
727                         return 2;
728                 return 0;
729         }
730
731         public static int test_0_marshal_point () {
732                 Point pt = new Point();
733                 pt.x = 1.25;
734                 pt.y = 3.5;
735                 
736                 return mono_test_marshal_point(pt);
737         }
738
739         public static int test_0_marshal_mixed_point () {
740                 MixedPoint mpt = new MixedPoint();
741                 mpt.x = 5;
742                 mpt.y = 6.75;
743                 
744                 return mono_test_marshal_mixed_point(mpt);
745         }
746
747         public static int test_0_marshal_bool_byref () {
748                 bool b = true;
749                 if (mono_test_marshal_bool_byref (99, ref b, 100) != 1)
750                         return 1;
751                 b = false;
752                 if (mono_test_marshal_bool_byref (99, ref b, 100) != 0)
753                         return 12;
754                 if (b != true)
755                         return 13;
756
757                 return 0;
758         }
759
760         public static int test_0_marshal_bool_as_I1 () {
761
762                 int ret;
763                 bool bTrue, bFalse;
764                 if ((ret = mono_test_marshal_bool_in_as_I1 (true, false)) != 0)
765                         return ret;
766
767                 if ((ret = mono_test_marshal_bool_out_as_I1 (out bTrue, out bFalse)) != 0)
768                         return ret;
769
770                 if(!bTrue)
771                         return 10;
772
773                 if(bFalse)
774                         return 11;
775
776                 if ((ret = mono_test_marshal_bool_ref_as_I1 (ref bTrue, ref bFalse)) != 0)
777                         return ret;
778
779                 if(bTrue)
780                         return 12;
781
782                 if(!bFalse)
783                         return 13;
784
785                 return 0;
786         }
787
788         public static int test_0_marshal_bool_as_U1 () {
789
790                 int ret;
791                 bool bTrue, bFalse;
792                 if ((ret = mono_test_marshal_bool_in_as_U1 (true, false)) != 0)
793                         return ret;
794
795                 if ((ret = mono_test_marshal_bool_out_as_U1 (out bTrue, out bFalse)) != 0)
796                         return ret;
797
798                 if(!bTrue)
799                         return 10;
800
801                 if(bFalse)
802                         return 11;
803
804                 if ((ret = mono_test_marshal_bool_ref_as_U1 (ref bTrue, ref bFalse)) != 0)
805                         return ret;
806
807                 if(bTrue)
808                         return 12;
809
810                 if(!bFalse)
811                         return 13;
812
813                 return 0;
814         }
815
816         public static int test_0_return_vtype () {
817                 SimpleStruct ss = mono_test_return_vtype (new IntPtr (5));
818
819                 if (!ss.a && ss.b && !ss.c && ss.d == "TEST" && ss.d2 == "TEST2")
820                         return 0;
821
822                 return 1;
823         }
824
825         public static int test_0_marshal_stringbuilder () {
826                 StringBuilder sb = new StringBuilder(255);
827                 sb.Append ("ABCD");
828                 mono_test_marshal_stringbuilder (sb, sb.Capacity);
829                 String res = sb.ToString();
830
831                 if (res != "This is my message.  Isn't it nice?")
832                         return 1;  
833
834                 // Test StringBuilder with default capacity (16)
835                 StringBuilder sb2 = new StringBuilder();
836                 mono_test_marshal_stringbuilder_default (sb2, sb2.Capacity);
837                 if (sb2.ToString () != "This is my messa")
838                         return 3;
839
840                 return 0;
841         }
842
843         public static int test_0_marshal_stringbuilder_append () {
844                 const String in_sentinel = "MONO_";
845                 const String out_sentinel = "CSHARP_";
846                 const int iterations = 100;
847                 StringBuilder sb = new StringBuilder(255);
848                 StringBuilder check = new StringBuilder(255);
849
850                 for (int i = 0; i < iterations; i++) {
851                         sb.Append (in_sentinel[i % in_sentinel.Length]);
852                         check.Append (out_sentinel[i % out_sentinel.Length]);
853
854                         mono_test_marshal_stringbuilder_append (sb, sb.Length);
855
856                         String res = sb.ToString();
857                         String checkRev = check.ToString();
858                         if (res != checkRev)
859                                 return 1;
860                 }
861
862                 // Test StringBuilder with default capacity (16)
863                 StringBuilder sb2 = new StringBuilder();
864                 mono_test_marshal_stringbuilder_default (sb2, sb2.Capacity);
865                 if (sb2.ToString () != "This is my messa")
866                         return 3;
867
868                 return 0;
869         }
870
871         public static int test_0_marshal_stringbuilder_unicode () {
872                 StringBuilder sb = new StringBuilder(255);
873                 mono_test_marshal_stringbuilder_unicode (sb, sb.Capacity);
874                 String res = sb.ToString();
875
876                 if (res != "This is my message.  Isn't it nice?")
877                         return 1;  
878
879                 // Test StringBuilder with default capacity (16)
880                 StringBuilder sb2 = new StringBuilder();
881                 mono_test_marshal_stringbuilder_unicode (sb2, sb2.Capacity);
882                 if (sb2.ToString () != "This is my messa")
883                         return 2;
884                 
885                 return 0;
886         }
887
888         public static int test_0_marshal_stringbuilder_out () {
889                 StringBuilder sb;
890                 mono_test_marshal_stringbuilder_out (out sb);
891                 
892                 if (sb.ToString () != "This is my message.  Isn't it nice?")
893                         return 1;  
894                 return 0;
895         }
896
897         public static int test_0_marshal_stringbuilder_out_unicode () {
898                 StringBuilder sb;
899                 mono_test_marshal_stringbuilder_out_unicode (out sb);
900
901                 if (sb.ToString () != "This is my message.  Isn't it nice?")
902                         return 1;  
903                 return 0;
904         }
905
906         public static int test_0_marshal_stringbuilder_ref () {
907                 StringBuilder sb = new StringBuilder ();
908                 sb.Append ("ABC");
909                 int res = mono_test_marshal_stringbuilder_ref (ref sb);
910                 if (res != 0)
911                         return 1;
912                 
913                 if (sb.ToString () != "This is my message.  Isn't it nice?")
914                         return 2;  
915                 return 0;
916         }
917
918         public static int test_0_marshal_empty_string_array () {
919                 return mono_test_marshal_empty_string_array (null);
920         }
921
922         public static int test_0_marshal_string_array () {
923                 return mono_test_marshal_string_array (new String [] { "ABC", "DEF" });
924         }
925
926         public static int test_0_marshal_unicode_string_array () {
927                 return mono_test_marshal_unicode_string_array (new String [] { "ABC", "DEF" }, new String [] { "ABC", "DEF" });
928         }
929
930         public static int test_0_marshal_stringbuilder_array () {
931                 StringBuilder sb1 = new StringBuilder ("ABC");
932                 StringBuilder sb2 = new StringBuilder ("DEF");
933
934                 int res = mono_test_marshal_stringbuilder_array (new StringBuilder [] { sb1, sb2 });
935                 if (res != 0)
936                         return res;
937                 if (sb1.ToString () != "DEF")
938                         return 5;
939                 if (sb2.ToString () != "ABC")
940                         return 6;
941                 return 0;
942         }
943
944         public static int test_0_last_error () {
945                 mono_test_last_error (5);
946                 if (Marshal.GetLastWin32Error () == 5)
947                         return 0;
948                 else
949                         return 1;
950         }
951
952         public static int test_0_entry_point_not_found () {
953
954                 try {
955                         mono_entry_point_not_found ();
956                         return 1;
957                 }
958                 catch (EntryPointNotFoundException) {
959                 }
960
961                 return 0;
962         }
963
964         public static int test_0_library_not_found () {
965
966                 try {
967                         mono_library_not_found ();
968                         return 1;
969                 }
970                 catch (DllNotFoundException) {
971                 }
972
973                 return 0;
974         }
975
976         /* Check that the runtime trims .dll from the library name */
977         public static int test_0_trim_dll_from_name () {
978
979                 mono_test_marshal_char_2 ('A');
980
981                 return 0;
982         }
983
984         /* Check that the runtime adds lib to to the library name */
985         public static int test_0_add_lib_to_name () {
986
987                 mono_test_marshal_char_3 ('A');
988
989                 return 0;
990         }
991
992         class C {
993                 public int i;
994         }
995
996         public static int test_0_asany () {
997                 if (mono_test_asany (5, 1) != 0)
998                         return 1;
999
1000                 if (mono_test_asany ("ABC", 2) != 0)
1001                         return 2;
1002
1003                 SimpleStruct2 ss2 = new  SimpleStruct2 ();
1004                 ss2.b = true;
1005                 ss2.d = "TEST";
1006                 ss2.e = 99;
1007                 ss2.f = 1.5;
1008                 ss2.g = 42;
1009                 ss2.h = 123L;
1010
1011                 if (mono_test_asany (ss2, 3) != 0)
1012                         return 3;
1013
1014                 if (mono_test_asany_unicode ("ABC", 4) != 0)
1015                         return 4;
1016
1017                 try {
1018                         C c = new C ();
1019                         c.i = 5;
1020                         mono_test_asany (c, 0);
1021                         return 5;
1022                 }
1023                 catch (ArgumentException) {
1024                 }
1025
1026                 try {
1027                         mono_test_asany (new Object (), 0);
1028                         return 6;
1029                 }
1030                 catch (ArgumentException) {
1031                 }
1032
1033                 return 0;
1034         }
1035
1036         /* AsAny marshalling + [In, Out] */
1037
1038         public static int test_0_asany_in () {
1039                 // Struct
1040                 AsAnyStruct str = new AsAnyStruct(1,2,3, "ABC");
1041                 mono_test_asany_in (str);
1042
1043                 // Formatted Class
1044                 AsAnyClass cls = new AsAnyClass(1,2,3, "ABC");
1045                 mono_test_asany_in (cls);
1046                 if ((cls.i != 1) || (cls.j != 2) || (cls.k != 3))
1047                         return 1;
1048
1049                 // Boxed Struct
1050                 object obj = new AsAnyStruct(1,2,3, "ABC");
1051                 mono_test_asany_in (obj);
1052                 str = (AsAnyStruct)obj;
1053                 if ((str.i != 1) || (str.j != 2) || (str.k != 3))
1054                         return 2;
1055
1056                 return 0;
1057         }
1058
1059         public static int test_0_asany_out () {
1060                 // Struct
1061                 AsAnyStruct str = new AsAnyStruct(1,2,3, "ABC");
1062                 mono_test_asany_out (str);
1063
1064                 // Formatted Class
1065                 AsAnyClass cls = new AsAnyClass(1,2,3, "ABC");
1066                 mono_test_asany_out (cls);
1067                 if ((cls.i != 10) || (cls.j != 20) || (cls.k != 30))
1068                         return 1;
1069
1070                 // Boxed Struct
1071                 object obj = new AsAnyStruct(1,2,3, "ABC");
1072                 mono_test_asany_out (obj);
1073                 str = (AsAnyStruct)obj;
1074                 if ((str.i != 10) || (str.j != 20) || (str.k != 30))
1075                         return 2;
1076
1077                 return 0;
1078         }
1079
1080         public static int test_0_asany_inout () {
1081                 // Struct
1082                 AsAnyStruct str = new AsAnyStruct(1,2,3, "ABC");
1083                 mono_test_asany_inout (str);
1084
1085                 // Formatted Class
1086                 AsAnyClass cls = new AsAnyClass(1,2,3, "ABC");
1087                 mono_test_asany_inout (cls);
1088                 if ((cls.i != 10) || (cls.j != 20) || (cls.k != 30))
1089                         return 1;
1090
1091                 // Boxed Struct
1092                 object obj = new AsAnyStruct(1,2,3, "ABC");
1093                 mono_test_asany_inout (obj);
1094                 str = (AsAnyStruct)obj;
1095                 if ((str.i != 10) || (str.j != 20) || (str.k != 30))
1096                         return 2;
1097
1098                 return 0;
1099         }
1100
1101         /* Byref String Array */
1102
1103         [DllImport ("libtest", EntryPoint="mono_test_marshal_byref_string_array")]
1104         public static extern int mono_test_marshal_byref_string_array (ref string[] data);
1105
1106         public static int test_0_byref_string_array () {
1107
1108                 string[] arr = null;
1109
1110                 if (mono_test_marshal_byref_string_array (ref arr) != 0)
1111                         return 1;
1112
1113                 arr = new string[] { "Alpha", "Beta", "Gamma" };
1114
1115                 if (mono_test_marshal_byref_string_array (ref arr) != 1)
1116                         return 2;
1117
1118                 /* FIXME: Test returned array and out case */
1119
1120                 return 0;
1121         }
1122
1123         /*
1124          * AMD64 small structs-by-value tests.
1125          */
1126
1127         /* TEST 1: 16 byte long INTEGER struct */
1128
1129         [StructLayout(LayoutKind.Sequential)]
1130         public struct Amd64Struct1 {
1131                 public int i;
1132                 public int j;
1133                 public int k;
1134                 public int l;
1135         }
1136         
1137         [DllImport ("libtest", EntryPoint="mono_test_marshal_amd64_pass_return_struct1")]
1138         public static extern Amd64Struct1 mono_test_marshal_amd64_pass_return_struct1 (Amd64Struct1 s);
1139         
1140         [DllImport ("libtest", EntryPoint="mono_test_marshal_amd64_pass_return_struct1_many_args")]
1141         public static extern Amd64Struct1 mono_test_marshal_amd64_pass_return_struct1_many_args (Amd64Struct1 s, int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8);
1142
1143         public static int test_0_amd64_struct1 () {
1144                 Amd64Struct1 s = new Amd64Struct1 ();
1145                 s.i = 5;
1146                 s.j = -5;
1147                 s.k = 0xffffff;
1148                 s.l = 0xfffffff;
1149
1150                 Amd64Struct1 s2 = mono_test_marshal_amd64_pass_return_struct1 (s);
1151
1152                 return ((s2.i == 6) && (s2.j == -4) && (s2.k == 0x1000000) && (s2.l == 0x10000000)) ? 0 : 1;
1153         }
1154
1155         public static int test_0_amd64_struct1_many_args () {
1156                 Amd64Struct1 s = new Amd64Struct1 ();
1157                 s.i = 5;
1158                 s.j = -5;
1159                 s.k = 0xffffff;
1160                 s.l = 0xfffffff;
1161
1162                 Amd64Struct1 s2 = mono_test_marshal_amd64_pass_return_struct1_many_args (s, 1, 2, 3, 4, 5, 6, 7, 8);
1163
1164                 return ((s2.i == 6) && (s2.j == -4) && (s2.k == 0x1000000) && (s2.l == 0x10000000 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8)) ? 0 : 1;
1165         }
1166
1167         /* TEST 2: 8 byte long INTEGER struct */
1168
1169         [StructLayout(LayoutKind.Sequential)]
1170         public struct Amd64Struct2 {
1171                 public int i;
1172                 public int j;
1173         }
1174         
1175         [DllImport ("libtest", EntryPoint="mono_test_marshal_amd64_pass_return_struct2")]
1176         public static extern Amd64Struct2 mono_test_marshal_amd64_pass_return_struct2 (Amd64Struct2 s);
1177
1178         public static int test_0_amd64_struct2 () {
1179                 Amd64Struct2 s = new Amd64Struct2 ();
1180                 s.i = 5;
1181                 s.j = -5;
1182
1183                 Amd64Struct2 s2 = mono_test_marshal_amd64_pass_return_struct2 (s);
1184
1185                 return ((s2.i == 6) && (s2.j == -4)) ? 0 : 1;
1186         }
1187
1188         /* TEST 3: 4 byte long INTEGER struct */
1189
1190         [StructLayout(LayoutKind.Sequential)]
1191         public struct Amd64Struct3 {
1192                 public int i;
1193         }
1194         
1195         [DllImport ("libtest", EntryPoint="mono_test_marshal_amd64_pass_return_struct3")]
1196         public static extern Amd64Struct3 mono_test_marshal_amd64_pass_return_struct3 (Amd64Struct3 s);
1197
1198         public static int test_0_amd64_struct3 () {
1199                 Amd64Struct3 s = new Amd64Struct3 ();
1200                 s.i = -5;
1201
1202                 Amd64Struct3 s2 = mono_test_marshal_amd64_pass_return_struct3 (s);
1203
1204                 return (s2.i == -4) ? 0 : 1;
1205         }
1206
1207         /* Test 4: 16 byte long FLOAT struct */
1208
1209         [StructLayout(LayoutKind.Sequential)]
1210         public struct Amd64Struct4 {
1211                 public double d1, d2;
1212         }
1213         
1214         [DllImport ("libtest", EntryPoint="mono_test_marshal_amd64_pass_return_struct4")]
1215         public static extern Amd64Struct4 mono_test_marshal_amd64_pass_return_struct4 (Amd64Struct4 s);
1216
1217         public static int test_0_amd64_struct4 () {
1218                 Amd64Struct4 s = new Amd64Struct4 ();
1219                 s.d1 = 5.0;
1220                 s.d2 = -5.0;
1221
1222                 Amd64Struct4 s2 = mono_test_marshal_amd64_pass_return_struct4 (s);
1223
1224                 return (s2.d1 == 6.0 && s2.d2 == -4.0) ? 0 : 1;
1225         }
1226
1227         /*
1228          * IA64 struct tests
1229          */
1230
1231         /* Test 5: Float HFA */
1232
1233         [StructLayout(LayoutKind.Sequential)]
1234         public struct TestStruct5 {
1235                 public float d1, d2;
1236         }
1237         
1238         [DllImport ("libtest", EntryPoint="mono_test_marshal_ia64_pass_return_struct5")]
1239         public static extern TestStruct5 mono_test_marshal_ia64_pass_return_struct5 (double d1, double d2, TestStruct5 s, int i, double f3, double f4);
1240
1241         public static int test_0_ia64_struct5 () {
1242                 TestStruct5 s = new TestStruct5 ();
1243                 s.d1 = 5.0f;
1244                 s.d2 = -5.0f;
1245
1246                 TestStruct5 s2 = mono_test_marshal_ia64_pass_return_struct5 (1.0, 2.0, s, 5, 3.0, 4.0);
1247
1248                 return (s2.d1 == 13.0 && s2.d2 == 7.0) ? 0 : 1;
1249         }
1250
1251         /* Test 6: Double HFA */
1252
1253         [StructLayout(LayoutKind.Sequential)]
1254         public struct TestStruct6 {
1255                 public double d1, d2;
1256         }
1257         
1258         [DllImport ("libtest", EntryPoint="mono_test_marshal_ia64_pass_return_struct6")]
1259         public static extern TestStruct6 mono_test_marshal_ia64_pass_return_struct6 (double d1, double d2, TestStruct6 s, int i, double f3, double f4);
1260
1261         public static int test_0_ia64_struct6 () {
1262                 TestStruct6 s = new TestStruct6 ();
1263                 s.d1 = 6.0;
1264                 s.d2 = -6.0;
1265
1266                 TestStruct6 s2 = mono_test_marshal_ia64_pass_return_struct6 (1.0, 2.0, s, 3, 4.0, 5.0);
1267
1268                 return (s2.d1 == 12.0 && s2.d2 == 3.0) ? 0 : 1;
1269         }
1270         
1271         /* Blittable class */
1272         [DllImport("libtest")]
1273         private static extern BlittableClass TestBlittableClass (BlittableClass vl);
1274
1275         public static int test_0_marshal_blittable_class () {
1276                 BlittableClass v1 = new BlittableClass ();
1277
1278                 /* Since it is blittable, it looks like it is passed as in/out */
1279                 BlittableClass v2 = TestBlittableClass (v1);
1280
1281                 if (v1.a != 2 || v1.b != 3)
1282                         return 1;
1283                 
1284                 if (v2.a != 2 || v2.b != 3)
1285                         return 2;
1286
1287                 // Test null
1288                 BlittableClass v3 = TestBlittableClass (null);
1289
1290                 if (v3.a != 42 || v3.b != 43)
1291                         return 3;
1292                 
1293                 return 0;
1294         }
1295
1296         /*
1297          * Generic structures
1298          */
1299
1300         [StructLayout(LayoutKind.Sequential)]
1301         public struct Amd64Struct1Gen<T> {
1302                 public T i;
1303                 public T j;
1304                 public T k;
1305                 public T l;
1306         }
1307         
1308         [DllImport ("libtest", EntryPoint="mono_test_marshal_amd64_pass_return_struct1")]
1309         public static extern Amd64Struct1Gen<int> mono_test_marshal_amd64_pass_return_struct1_gen (Amd64Struct1Gen<int> s);
1310
1311         public static int test_0_amd64_struct1_gen () {
1312                 Amd64Struct1Gen<int> s = new Amd64Struct1Gen<int> ();
1313                 s.i = 5;
1314                 s.j = -5;
1315                 s.k = 0xffffff;
1316                 s.l = 0xfffffff;
1317
1318                 Amd64Struct1Gen<int> s2 = mono_test_marshal_amd64_pass_return_struct1_gen (s);
1319
1320                 return ((s2.i == 6) && (s2.j == -4) && (s2.k == 0x1000000) && (s2.l == 0x10000000)) ? 0 : 1;
1321         }
1322
1323         /*
1324          * Other tests
1325          */
1326
1327         public static int test_0_marshal_byval_class () {
1328                 SimpleObj obj0 = new SimpleObj ();
1329                 obj0.str = "T1";
1330                 obj0.i = 4;
1331                 
1332                 if (class_marshal_test0 (obj0) != 0)
1333                         return 1;
1334
1335                 return 0;
1336         }
1337
1338         public static int test_0_marshal_byval_class_null () {
1339                 if (class_marshal_test4 (null) != 0)
1340                         return 1;
1341
1342                 return 0;
1343         }
1344
1345         public static int test_0_marshal_out_class () {
1346                 SimpleObj obj1;
1347
1348                 class_marshal_test1 (out obj1);
1349
1350                 if (obj1.str != "ABC")
1351                         return 1;
1352
1353                 if (obj1.i != 5)
1354                         return 2;
1355
1356                 return 0;
1357         }
1358
1359         public static int test_0_marshal_string () {
1360                 return string_marshal_test0 ("TEST0");
1361         }
1362
1363         public static int test_0_marshal_out_string () {
1364                 string res;
1365                 
1366                 string_marshal_test1 (out res);
1367
1368                 if (res != "TEST1")
1369                         return 1;
1370
1371                 return 0;
1372         }
1373
1374         public static int test_0_marshal_byref_string () {
1375                 string res = "TEST1";
1376
1377                 int r = string_marshal_test2 (ref res);
1378                 if (r != 0)
1379                         return 1;
1380                 if (res != "TEST2")
1381                         return 2;
1382                 return 0;
1383         }
1384
1385         public static int test_0_marshal_null_string () {
1386                 return string_marshal_test3 (null);
1387         }
1388
1389 #if FALSE
1390         [DllImport ("libtest", EntryPoint="mono_test_stdcall_mismatch_1", CallingConvention=CallingConvention.StdCall)]
1391         public static extern int mono_test_stdcall_mismatch_1 (int a, int b, int c);
1392
1393         /* Test mismatched called conventions, the native function is cdecl */
1394         public static int test_0_stdcall_mismatch_1 () {
1395                 mono_test_stdcall_mismatch_1 (0, 1, 2);
1396                 return 0;
1397         }
1398
1399         [DllImport ("libtest", EntryPoint="mono_test_stdcall_mismatch_2", CallingConvention=CallingConvention.Cdecl)]
1400         public static extern int mono_test_stdcall_mismatch_2 (int a, int b, int c);
1401
1402         /* Test mismatched called conventions, the native function is stdcall */
1403         public static int test_0_stdcall_mismatch_2 () {
1404                 mono_test_stdcall_mismatch_2 (0, 1, 2);
1405                 return 0;
1406         }
1407 #endif
1408
1409         [DllImport ("libtest", EntryPoint="mono_test_stdcall_name_mangling", CallingConvention=CallingConvention.StdCall)]
1410         public static extern int mono_test_stdcall_name_mangling (int a, int b, int c);
1411
1412         public static int test_0_stdcall_name_mangling () {
1413                 return mono_test_stdcall_name_mangling (0, 1, 2) == 3 ? 0 : 1;
1414         }
1415
1416         /* Float test */
1417
1418         [DllImport ("libtest", EntryPoint="mono_test_marshal_pass_return_float")]
1419         public static extern float mono_test_marshal_pass_return_float (float f);
1420
1421         public static int test_0_pass_return_float () {
1422                 float f = mono_test_marshal_pass_return_float (1.5f);
1423
1424                 return (f == 2.5f) ? 0 : 1;
1425         }
1426
1427         /*
1428          * Pointers to structures can not be passed
1429          */
1430
1431         /* This seems to be allowed by MS in some cases */
1432         /*
1433         public struct CharInfo {
1434                 public char Character;
1435                 public short Attributes;
1436         }
1437
1438         [DllImport ("libtest", EntryPoint="mono_test_marshal_struct")]
1439         public static unsafe extern int mono_test_marshal_ptr_to_struct (CharInfo *ptr);
1440
1441         public static unsafe int test_0_marshal_ptr_to_struct () {
1442                 CharInfo [] buffer = new CharInfo [1];
1443                 fixed (CharInfo *ptr = &buffer [0]) {
1444                         try {
1445                                 mono_test_marshal_ptr_to_struct (ptr);
1446                                 return 1;
1447                         }
1448                         catch (MarshalDirectiveException) {
1449                                 return 0;
1450                         }
1451                 }
1452                 return 1;
1453         }
1454         */
1455
1456         /*
1457          * LPWStr marshalling
1458          */
1459
1460         [DllImport("libtest", EntryPoint="test_lpwstr_marshal")]
1461         [return: MarshalAs(UnmanagedType.LPWStr)]
1462         private static extern string mono_test_marshal_lpwstr_marshal(
1463                 [MarshalAs(UnmanagedType.LPWStr)] string s,
1464                 int length );
1465
1466         [DllImport("libtest", EntryPoint="test_lpwstr_marshal", CharSet=CharSet.Unicode)]
1467         private static extern string mono_test_marshal_lpwstr_marshal2(
1468                 string s,
1469                 int length );
1470
1471         [DllImport("libtest", EntryPoint="test_lpwstr_marshal_out")]
1472         private static extern void mono_test_marshal_lpwstr_out_marshal(
1473                 [MarshalAs(UnmanagedType.LPWStr)] out string s);
1474
1475         [DllImport("libtest", EntryPoint="test_lpwstr_marshal_out", CharSet=CharSet.Unicode)]
1476         private static extern void mono_test_marshal_lpwstr_out_marshal2(
1477                 out string s);
1478
1479         public static int test_0_pass_return_lwpstr () {
1480                 string s;
1481                 
1482                 mono_test_marshal_lpwstr_out_marshal (out s);
1483
1484                 if (s != "ABC")
1485                         return 1;
1486
1487                 s = null;
1488                 mono_test_marshal_lpwstr_out_marshal2 (out s);
1489
1490                 if (s != "ABC")
1491                         return 2;
1492                 
1493                 return 0;               
1494         }
1495
1496         public static int test_0_out_lwpstr () {
1497                 string s = "ABC";
1498                 
1499                 string res = mono_test_marshal_lpwstr_marshal (s, s.Length);
1500
1501                 if (res != "ABC")
1502                         return 1;
1503
1504                 string res2 = mono_test_marshal_lpwstr_marshal2 (s, s.Length);
1505
1506                 if (res2 != "ABC")
1507                         return 2;
1508                 
1509                 return 0;               
1510         }
1511
1512         /*
1513          * Byref bool marshalling
1514          */
1515
1516         [DllImport("libtest")]
1517         extern static int marshal_test_ref_bool
1518         (
1519                 int i, 
1520                 [MarshalAs(UnmanagedType.I1)] ref bool b1, 
1521                 [MarshalAs(UnmanagedType.VariantBool)] ref bool b2, 
1522                 ref bool b3
1523         );
1524
1525         public static int test_0_pass_byref_bool () {
1526                 for (int i = 0; i < 8; i++)
1527                 {
1528                         bool b1 = (i & 4) != 0;
1529                         bool b2 = (i & 2) != 0;
1530                         bool b3 = (i & 1) != 0;
1531                         bool orig_b1 = b1, orig_b2 = b2, orig_b3 = b3;
1532                         if (marshal_test_ref_bool(i, ref b1, ref b2, ref b3) != 0)
1533                                 return 4 * i + 1;
1534                         if (b1 != !orig_b1)
1535                                 return 4 * i + 2;
1536                         if (b2 != !orig_b2)
1537                                 return 4 * i + 3;
1538                         if (b3 != !orig_b3)
1539                                 return 4 * i + 4;
1540                 }
1541
1542                 return 0;
1543         }
1544
1545         /*
1546          * Bool struct field marshalling
1547          */
1548
1549         struct BoolStruct
1550         {
1551                 public int i;
1552                 [MarshalAs(UnmanagedType.I1)] public bool b1;
1553                 [MarshalAs(UnmanagedType.VariantBool)] public bool b2;
1554                 public bool b3;
1555         }
1556
1557         [DllImport("libtest")]
1558         extern static int marshal_test_bool_struct(ref BoolStruct s);
1559
1560         public static int test_0_pass_bool_in_struct () {
1561                 for (int i = 0; i < 8; i++)
1562                 {
1563                         BoolStruct s = new BoolStruct();
1564                         s.i = i;
1565                         s.b1 = (i & 4) != 0;
1566                         s.b2 = (i & 2) != 0;
1567                         s.b3 = (i & 1) != 0;
1568                         BoolStruct orig = s;
1569                         if (marshal_test_bool_struct(ref s) != 0)
1570                                 return 4 * i + 33;
1571                         if (s.b1 != !orig.b1)
1572                                 return 4 * i + 34;
1573                         if (s.b2 != !orig.b2)
1574                                 return 4 * i + 35;
1575                         if (s.b3 != !orig.b3)
1576                                 return 4 * i + 36;
1577                 }
1578
1579                 return 0;
1580         }
1581
1582         /*
1583          * Alignment of structs containing longs
1584          */
1585
1586         struct LongStruct2 {
1587                 public long l;
1588         }
1589
1590         struct LongStruct {
1591                 public int i;
1592                 public LongStruct2 l;
1593         }
1594
1595         [DllImport("libtest")]
1596         extern static int mono_test_marshal_long_struct (ref LongStruct s);
1597
1598         public static int test_47_pass_long_struct () {
1599                 LongStruct s = new LongStruct ();
1600                 s.i = 5;
1601                 s.l = new LongStruct2 ();
1602                 s.l.l = 42;
1603
1604                 return mono_test_marshal_long_struct (ref s);
1605         }
1606
1607         /*
1608          * Invoking pinvoke methods through delegates
1609          */
1610
1611         delegate int MyDelegate (string name);
1612
1613         [DllImport ("libtest", EntryPoint="mono_test_puts_static")]
1614         public static extern int puts_static (string name);
1615
1616         public static int test_0_invoke_pinvoke_through_delegate () {
1617                 puts_static ("A simple Test for PInvoke 1");
1618
1619                 MyDelegate d = new MyDelegate (puts_static);
1620                 d ("A simple Test for PInvoke 2");
1621
1622                 object [] args = {"A simple Test for PInvoke 3"};
1623                 d.DynamicInvoke (args);
1624
1625                 return 0;
1626         }
1627
1628         /*
1629          * Missing virtual pinvoke methods
1630          */
1631
1632         public class T {
1633
1634                 public virtual object MyClone ()
1635                 {
1636                         return null;
1637                 }
1638         }
1639
1640         public class T2 : T {
1641                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1642                 public override extern object MyClone ();
1643         }
1644
1645         public static int test_0_missing_virtual_pinvoke_method () {
1646                 T2 t = new T2 ();
1647
1648                 try {
1649                         t.MyClone ();
1650                 } catch (Exception ex) {
1651                         return 0;
1652                 }
1653                 
1654                 return 1;
1655         }
1656
1657         /*
1658          * Marshalling of type 'object'
1659          */
1660
1661         [DllImport ("libtest", EntryPoint="mono_test_marshal_class")]
1662         public static extern SimpleClass mono_test_marshal_object (int i, int j, int k, object ss, int l);
1663
1664         public static int test_0_marshal_object () {
1665                 try {
1666                         mono_test_marshal_object (0, 0, 0, null, 0);
1667                         return 1;
1668                 } catch (Exception) {
1669                         return 0;
1670                 }
1671         }
1672
1673         /*
1674          * Marshalling of DateTime to OLE DATE (double)
1675          */
1676         [DllImport ("libtest", EntryPoint="mono_test_marshal_date_time")]
1677         public static extern double mono_test_marshal_date_time (DateTime d, out DateTime d2);
1678
1679         public static int test_0_marshal_date_time () {
1680                 DateTime d = new DateTime (2009, 12, 6);
1681                 DateTime d2;
1682                 double d3 = mono_test_marshal_date_time (d, out d2);
1683                 if (d3 != 40153.0)
1684                         return 1;
1685                 if (d2 != d)
1686                         return 2;
1687                 return 0;
1688         }
1689
1690         /*
1691          * Calling pinvoke functions dynamically using calli
1692          */
1693         
1694         [DllImport("libtest")]
1695         private static extern IntPtr mono_test_marshal_lookup_symbol (string fileName);
1696
1697         delegate void CalliDel (IntPtr a, int[] f);
1698
1699         public static int test_0_calli_dynamic () {
1700                 /* we need the cdecl version because the icall convention demands it under Windows */
1701                 IntPtr func = mono_test_marshal_lookup_symbol ("mono_test_marshal_inout_array_cdecl");
1702
1703                 DynamicMethod dm = new DynamicMethod ("calli", typeof (void), new Type [] { typeof (IntPtr), typeof (int[]) });
1704
1705                 var il = dm.GetILGenerator ();
1706                 var signature = SignatureHelper.GetMethodSigHelper (CallingConvention.Cdecl, typeof (void));
1707
1708                 il.Emit (OpCodes.Ldarg, 1);
1709                 signature.AddArgument (typeof (byte[]));
1710
1711                 il.Emit (OpCodes.Ldarg_0);
1712
1713                 il.Emit (OpCodes.Calli, signature);
1714                 il.Emit (OpCodes.Ret);
1715
1716                 var f = (CalliDel)dm.CreateDelegate (typeof (CalliDel));
1717
1718                 int[] arr = new int [1000];
1719                 for (int i = 0; i < 50; ++i)
1720                         arr [i] = (int)i;
1721                 f (func, arr);
1722                 if (arr.Length != 1000)
1723                         return 1;
1724                 for (int i = 0; i < 50; ++i)
1725                         if (arr [i] != 50 - i)
1726                                 return 2;
1727
1728                 return 0;
1729         }
1730
1731
1732         /*char array marshaling */
1733         [DllImport ("libtest", EntryPoint="mono_test_marshal_ansi_char_array", CharSet=CharSet.Ansi)]
1734         public static extern int mono_test_marshal_ansi_char_array (char[] a1);
1735
1736         public static int test_0_marshal_ansi_char_array () {
1737                 char[] buf = new char [32];
1738                 buf [0] = 'q';
1739                 buf [1] = 'w';
1740                 buf [2] = 'e';
1741                 buf [3] = 'r';
1742
1743                 if (mono_test_marshal_ansi_char_array (buf) != 0)
1744                         return 1;
1745
1746                 string s = new string (buf);
1747                 if (s.StartsWith ("qwer"))
1748                         return 0;
1749                 else
1750                         return 2;
1751         }
1752
1753         /*char array marshaling */
1754         [DllImport ("libtest", EntryPoint="mono_test_marshal_unicode_char_array", CharSet=CharSet.Unicode)]
1755         public static extern int mono_test_marshal_unicode_char_array (char[] a1);
1756
1757         public static int test_0_marshal_unicode_char_array () {
1758                 char[] buf = new char [32];
1759                 buf [0] = 'q';
1760                 buf [1] = 'w';
1761                 buf [2] = 'e';
1762                 buf [3] = 'r';
1763
1764                 if (mono_test_marshal_unicode_char_array (buf) != 0)
1765                         return 1;
1766
1767                 string s = new string (buf);
1768                 if (s.StartsWith ("abcdef"))
1769                         return 0;
1770                 else
1771                         return 2;
1772         }
1773
1774         [DllImport ("libtest", EntryPoint="mono_test_marshal_lpstr")]
1775         public static extern int mono_test_marshal_lpstr ([MarshalAs(UnmanagedType.LPStr)] string str);
1776
1777         public static int test_0_mono_test_marshal_lpstr () {
1778                 string str = "ABC";
1779
1780                 if (mono_test_marshal_lpstr (str) != 0)
1781                         return 1;
1782
1783                 return 0;
1784         }
1785
1786         [DllImport ("libtest", EntryPoint="mono_test_marshal_lpwstr")]
1787         public static extern int mono_test_marshal_lpwstr ([MarshalAs(UnmanagedType.LPWStr)] string str);
1788
1789         public static int test_0_mono_test_marshal_lpwstr () {
1790                 string str = "ABC";
1791
1792                 if (mono_test_marshal_lpwstr (str) != 0)
1793                         return 1;
1794
1795                 return 0;
1796         }
1797
1798
1799         [method: DllImport ("libtest", EntryPoint="mono_test_marshal_return_lpstr")]
1800         [return: MarshalAs(UnmanagedType.LPStr)]
1801         public static extern string mono_test_marshal_return_lpstr ();
1802
1803         public static int test_0_mono_test_marshal_return_lpstr () {
1804                 string str = mono_test_marshal_return_lpstr ();
1805                 if ("XYZ" == str)
1806                         return 0;
1807
1808                 return 1;
1809         }
1810
1811         [method: DllImport ("libtest", EntryPoint="mono_test_marshal_return_lpwstr")]
1812         [return: MarshalAs(UnmanagedType.LPWStr)]
1813         public static extern string mono_test_marshal_return_lpwstr ();
1814
1815         public static int test_0_mono_test_marshal_return_lpwstr () {
1816                 string str = mono_test_marshal_return_lpwstr ();
1817                 if ("XYZ" == str)
1818                         return 0;
1819
1820                 return 1;
1821         }
1822
1823         [DllImport ("libtest", EntryPoint="mono_test_has_thiscall")]
1824         public static extern int mono_test_has_thiscall ();
1825
1826         [DllImport ("libtest", EntryPoint = "_mono_test_native_thiscall1", CallingConvention=CallingConvention.ThisCall)]
1827         public static extern int mono_test_native_thiscall (int a);
1828
1829         [DllImport ("libtest", EntryPoint = "_mono_test_native_thiscall2", CallingConvention=CallingConvention.ThisCall)]
1830         public static extern int mono_test_native_thiscall (int a, int b);
1831
1832         [DllImport ("libtest", EntryPoint = "_mono_test_native_thiscall3", CallingConvention=CallingConvention.ThisCall)]
1833         public static extern int mono_test_native_thiscall (int a, int b, int c);
1834
1835         [DllImport ("libtest", EntryPoint = "_mono_test_native_thiscall1", CallingConvention=CallingConvention.ThisCall)]
1836         public static extern int mono_test_native_thiscall (TinyStruct a);
1837
1838         [DllImport ("libtest", EntryPoint = "_mono_test_native_thiscall2", CallingConvention=CallingConvention.ThisCall)]
1839         public static extern int mono_test_native_thiscall (TinyStruct a, int b);
1840
1841         [DllImport ("libtest", EntryPoint = "_mono_test_native_thiscall3", CallingConvention=CallingConvention.ThisCall)]
1842         public static extern int mono_test_native_thiscall (TinyStruct a, int b, int c);
1843
1844         public static int test_0_native_thiscall ()
1845         {
1846                 if (mono_test_has_thiscall () == 0)
1847                         return 0;
1848
1849                 if (mono_test_native_thiscall (1968329802) != 1968329802)
1850                         return 1;
1851
1852                 if (mono_test_native_thiscall (268894549, 1212675791) != 1481570339)
1853                         return 2;
1854
1855                 if (mono_test_native_thiscall (1288082683, -421187449, -1733670329) != -866775098)
1856                         return 3;
1857
1858                 if (mono_test_native_thiscall (new TinyStruct(1968329802)) != 1968329802)
1859                         return 4;
1860
1861                 if (mono_test_native_thiscall (new TinyStruct(268894549), 1212675791) != 1481570339)
1862                         return 5;
1863
1864                 if (mono_test_native_thiscall (new TinyStruct(1288082683), -421187449, -1733670329) != -866775098)
1865                         return 6;
1866
1867                 return 0;
1868         }
1869
1870         [DllImport ("libtest", EntryPoint = "mono_test_marshal_return_single_double_struct")]
1871         public static extern SingleDoubleStruct mono_test_marshal_return_single_double_struct ();
1872
1873         public static int test_0_x86_single_double_struct_ret () {
1874                 double d = mono_test_marshal_return_single_double_struct ().d;
1875                 if (d != 3.0)
1876                         return 1;
1877                 else
1878                         return 0;
1879         }
1880 }
1881