2006-02-16 Martin Baulig <martin@ximian.com>
[mono.git] / mono / tests / pinvoke2.cs
1 using System;
2 using System.Text;
3 using System.Runtime.InteropServices;
4 using System.Runtime.CompilerServices;
5
6 public class Tests {
7
8         public static int delegate_test (int a)
9         {
10                 if (a == 2)
11                         return 0;
12
13                 return 1;
14         }
15         
16         [StructLayout (LayoutKind.Sequential)]
17         public struct SimpleStruct {
18                 public bool a;
19                 public bool b;
20                 public bool c;
21                 public string d;
22                 [MarshalAs(UnmanagedType.LPWStr)]
23                 public string d2;
24         }
25
26         [StructLayout (LayoutKind.Sequential)]
27         public struct SimpleStruct2 {
28                 public bool a;
29                 public bool b;
30                 public bool c;
31                 public string d;
32                 public byte e;
33                 public double f;
34                 public byte g;
35                 public long h;
36         }
37
38         [StructLayout (LayoutKind.Sequential, Size=0)]
39         public struct EmptyStruct {
40         }
41
42         [StructLayout (LayoutKind.Sequential)]
43         public struct DelegateStruct {
44                 public int a;
45                 public SimpleDelegate del;
46                 [MarshalAs(UnmanagedType.FunctionPtr)] 
47                 public SimpleDelegate del2;
48         }
49
50         /* sparcv9 has complex conventions when passing structs with doubles in them 
51            by value, some simple tests for them */
52         [StructLayout (LayoutKind.Sequential)]
53         public struct Point {
54                 public double x;
55                 public double y;
56         }
57
58         [StructLayout (LayoutKind.Sequential)]
59         public struct MixedPoint {
60                 public int x;
61                 public double y;
62         }
63
64         [StructLayout (LayoutKind.Sequential)]
65         public class SimpleClass {
66                 public bool a;
67                 public bool b;
68                 public bool c;
69                 public string d;
70                 public byte e;
71                 public double f;
72                 public byte g;
73                 public long h;
74         }
75
76         [StructLayout (LayoutKind.Sequential)]
77         public class EmptyClass {
78         }
79
80         [StructLayout (LayoutKind.Sequential)]
81         public struct LongAlignStruct {
82                 public int a;
83                 public long b;
84                 public long c;
85         }
86
87         [StructLayout(LayoutKind.Sequential)]
88         public class VectorList
89         {
90                 public int a = 1;
91                 public int b = 2;
92         }
93
94         [StructLayout (LayoutKind.Sequential)]
95         class SimpleObj
96         {
97                 public string str;
98                 public int i;
99         }
100
101         [DllImport ("libnot-found", EntryPoint="not_found")]
102         public static extern int mono_library_not_found ();
103
104         [DllImport ("libtest", EntryPoint="not_found")]
105         public static extern int mono_entry_point_not_found ();
106
107         [DllImport ("libtest.dll", EntryPoint="mono_test_marshal_char")]
108         public static extern int mono_test_marshal_char_2 (char a1);
109
110         [DllImport ("test", EntryPoint="mono_test_marshal_char")]
111         public static extern int mono_test_marshal_char_3 (char a1);
112
113         [DllImport ("libtest", EntryPoint="mono_test_marshal_char")]
114         public static extern int mono_test_marshal_char (char a1);
115
116         [DllImport ("libtest", EntryPoint="mono_test_marshal_char_array", CharSet=CharSet.Unicode)]
117         public static extern int mono_test_marshal_char_array (char[] a1);
118
119         [DllImport ("libtest", EntryPoint="mono_test_marshal_bool_byref")]
120         public static extern int mono_test_marshal_bool_byref (int a, ref bool b, int c);
121
122         [DllImport ("libtest", EntryPoint="mono_test_marshal_array")]
123         public static extern int mono_test_marshal_array (int [] a1);
124
125         [DllImport ("libtest", EntryPoint="mono_test_marshal_empty_string_array")]
126         public static extern int mono_test_marshal_empty_string_array (string [] a1);
127
128         [DllImport ("libtest", EntryPoint="mono_test_marshal_string_array")]
129         public static extern int mono_test_marshal_string_array (string [] a1);
130
131         [DllImport ("libtest", EntryPoint="mono_test_marshal_unicode_string_array", CharSet=CharSet.Unicode)]
132         public static extern int mono_test_marshal_unicode_string_array (string [] a1, [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStr)]string [] a2);
133
134         [DllImport ("libtest", EntryPoint="mono_test_marshal_stringbuilder_array")]
135         public static extern int mono_test_marshal_stringbuilder_array (StringBuilder [] a1);   
136
137         [DllImport ("libtest", EntryPoint="mono_test_marshal_inout_array")]
138         public static extern int mono_test_marshal_inout_array ([In, Out] int [] a1);
139
140         [DllImport ("libtest", EntryPoint="mono_test_marshal_out_array")]
141         public static extern int mono_test_marshal_out_array ([Out] [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] int [] a1, int n);
142
143         [DllImport ("libtest", EntryPoint="mono_test_marshal_inout_nonblittable_array", CharSet = CharSet.Unicode)]
144         public static extern int mono_test_marshal_inout_nonblittable_array ([In, Out] char [] a1);
145         
146         [DllImport ("libtest", EntryPoint="mono_test_marshal_struct")]
147         public static extern int mono_test_marshal_struct (SimpleStruct ss);
148
149         [DllImport ("libtest", EntryPoint="mono_test_marshal_struct2")]
150         public static extern int mono_test_marshal_struct2 (SimpleStruct2 ss);
151
152         [DllImport ("libtest", EntryPoint="mono_test_marshal_struct2_2")]
153         public static extern int mono_test_marshal_struct2_2 (int i, int j, int k, SimpleStruct2 ss);
154
155         [DllImport ("libtest", EntryPoint="mono_test_marshal_byref_struct")]
156         public static extern int mono_test_marshal_byref_struct (ref SimpleStruct ss, bool a, bool b, bool c, String d);
157
158         [DllImport ("libtest", EntryPoint="mono_test_marshal_byref_struct")]
159         public static extern int mono_test_marshal_byref_struct_in ([In] ref SimpleStruct ss, bool a, bool b, bool c, String d);
160
161         [DllImport ("libtest", EntryPoint="mono_test_marshal_byref_struct")]
162         public static extern int mono_test_marshal_byref_struct_inout ([In, Out] ref SimpleStruct ss, bool a, bool b, bool c, String d);
163
164         [DllImport ("libtest", EntryPoint="mono_test_marshal_point")]
165         public static extern int mono_test_marshal_point (Point p);
166
167         [DllImport ("libtest", EntryPoint="mono_test_marshal_mixed_point")]
168         public static extern int mono_test_marshal_mixed_point (MixedPoint p);
169
170         [DllImport ("libtest", EntryPoint="mono_test_empty_struct")]
171         public static extern int mono_test_empty_struct (int a, EmptyStruct es, int b);
172
173         [DllImport ("libtest", EntryPoint="mono_test_marshal_struct_array")]
174         public static extern int mono_test_marshal_struct_array (SimpleStruct2[] ss);
175
176         [DllImport ("libtest", EntryPoint="mono_test_marshal_long_align_struct_array")]
177         public static extern int mono_test_marshal_long_align_struct_array (LongAlignStruct[] ss);
178
179         [DllImport ("libtest", EntryPoint="mono_test_marshal_class")]
180         public static extern SimpleClass mono_test_marshal_class (int i, int j, int k, SimpleClass ss, int l);
181
182         [DllImport ("libtest", EntryPoint="mono_test_marshal_byref_class")]
183         public static extern int mono_test_marshal_byref_class (ref SimpleClass ss);
184
185         [DllImport ("libtest", EntryPoint="mono_test_marshal_delegate")]
186         public static extern int mono_test_marshal_delegate (SimpleDelegate d);
187
188         [DllImport ("libtest", EntryPoint="mono_test_marshal_delegate_struct")]
189         public static extern DelegateStruct mono_test_marshal_delegate_struct (DelegateStruct d);
190
191         [DllImport ("libtest", EntryPoint="mono_test_marshal_return_delegate")]
192         public static extern SimpleDelegate mono_test_marshal_return_delegate (SimpleDelegate d);
193
194         [DllImport ("libtest", EntryPoint="mono_test_return_vtype")]
195         public static extern SimpleStruct mono_test_return_vtype (IntPtr i);
196
197         [DllImport ("libtest", EntryPoint="mono_test_marshal_stringbuilder")]
198         public static extern void mono_test_marshal_stringbuilder (StringBuilder sb, int len);
199
200         [DllImport ("libtest", EntryPoint="mono_test_marshal_stringbuilder_unicode", CharSet=CharSet.Unicode)]
201         public static extern void mono_test_marshal_stringbuilder_unicode (StringBuilder sb, int len);
202
203         [DllImport ("libtest", EntryPoint="mono_test_last_error", SetLastError=true)]
204         public static extern void mono_test_last_error (int err);
205
206         [DllImport ("libtest", EntryPoint="mono_test_asany")]
207         public static extern int mono_test_asany ([MarshalAs (UnmanagedType.AsAny)] object o, int what);
208
209         [DllImport ("libtest", EntryPoint="mono_test_asany", CharSet=CharSet.Unicode)]
210         public static extern int mono_test_asany_unicode ([MarshalAs (UnmanagedType.AsAny)] object o, int what);
211
212         [DllImport ("libtest")]
213         static extern int class_marshal_test0 (SimpleObj obj);
214
215         [DllImport ("libtest")]
216         static extern void class_marshal_test1 (out SimpleObj obj);
217
218         [DllImport ("libtest")]
219         static extern int class_marshal_test4 (SimpleObj obj);
220         
221         [DllImport ("libtest")]
222         static extern int string_marshal_test0 (string str);
223
224         [DllImport ("libtest")]
225         static extern void string_marshal_test1 (out string str);
226
227         [DllImport ("libtest")]
228         static extern int string_marshal_test2 (ref string str);
229
230         [DllImport ("libtest")]
231         static extern int string_marshal_test3 (string str);
232
233         public delegate int SimpleDelegate (int a);
234
235         public static int Main (string[] args) {
236                 return TestDriver.RunTests (typeof (Tests), args);
237         }
238
239         public static int test_0_marshal_char () {
240                 return mono_test_marshal_char ('a');
241         }
242
243         public static int test_0_marshal_char_array () {
244                 // a unicode char[] is implicitly marshalled as [Out]
245                 char[] buf = new char [32];
246                 mono_test_marshal_char_array (buf);
247                 string s = new string (buf);
248                 if (s.StartsWith ("abcdef"))
249                         return 0;
250                 else
251                         return 1;
252         }
253
254         public static int test_1225_marshal_array () {
255                 int [] a1 = new int [50];
256                 for (int i = 0; i < 50; i++)
257                         a1 [i] = i;
258
259                 return mono_test_marshal_array (a1);
260         }
261
262         public static int test_1225_marshal_inout_array () {
263                 int [] a1 = new int [50];
264                 for (int i = 0; i < 50; i++)
265                         a1 [i] = i;
266
267                 int res = mono_test_marshal_inout_array (a1);
268
269                 for (int i = 0; i < 50; i++)
270                         if (a1 [i] != 50 - i) {
271                                 Console.WriteLine ("X: " + i + " " + a1 [i]);
272                                 return 2;
273                         }
274
275                 return res;
276         }
277
278         public static int test_0_marshal_out_array () {
279                 int [] a1 = new int [50];
280
281                 int res = mono_test_marshal_out_array (a1, 0);
282
283                 for (int i = 0; i < 50; i++)
284                         if (a1 [i] != i) {
285                                 Console.WriteLine ("X: " + i + " " + a1 [i]);
286                                 return 2;
287                         }
288
289                 return 0;
290         }
291
292         public static int test_0_marshal_inout_nonblittable_array () {
293                 char [] a1 = new char [10];
294                 for (int i = 0; i < 10; i++)
295                         a1 [i] = "Hello, World" [i];
296
297                 int res = mono_test_marshal_inout_nonblittable_array (a1);
298
299                 for (int i = 0; i < 10; i++)
300                         if (a1 [i] != 'F')
301                                 return 2;
302
303                 return res;
304         }
305
306         public static int test_0_marshal_struct () {
307                 SimpleStruct ss = new  SimpleStruct ();
308                 ss.b = true;
309                 ss.d = "TEST";
310                 
311                 return mono_test_marshal_struct (ss);
312         }
313
314         public static int test_0_marshal_struct2 () {
315                 SimpleStruct2 ss2 = new  SimpleStruct2 ();
316                 ss2.b = true;
317                 ss2.d = "TEST";
318                 ss2.e = 99;
319                 ss2.f = 1.5;
320                 ss2.g = 42;
321                 ss2.h = 123L;
322
323                 return mono_test_marshal_struct2 (ss2);
324         }
325
326         public static int test_0_marshal_struct3 () {
327                 SimpleStruct2 ss2 = new  SimpleStruct2 ();
328                 ss2.b = true;
329                 ss2.d = "TEST";
330                 ss2.e = 99;
331                 ss2.f = 1.5;
332                 ss2.g = 42;
333                 ss2.h = 123L;
334
335                 return mono_test_marshal_struct2_2 (10, 11, 12, ss2);
336         }
337
338         public static int test_0_marshal_empty_struct () {
339                 EmptyStruct es = new EmptyStruct ();
340
341                 if (mono_test_empty_struct (1, es, 2) != 0)
342                         return 1;
343                 
344                 return 0;
345         }
346
347         public static int test_0_marshal_struct_array () {
348                 SimpleStruct2[] ss_arr = new SimpleStruct2 [2];
349
350                 SimpleStruct2 ss2 = new SimpleStruct2 ();
351                 ss2.b = true;
352                 ss2.d = "TEST";
353                 ss2.e = 99;
354                 ss2.f = 1.5;
355                 ss2.g = 42;
356                 ss2.h = 123L;
357
358                 ss_arr [0] = ss2;
359
360                 ss2.b = false;
361                 ss2.d = "TEST2";
362                 ss2.e = 100;
363                 ss2.f = 2.5;
364                 ss2.g = 43;
365                 ss2.h = 124L;
366
367                 ss_arr [1] = ss2;
368
369                 return mono_test_marshal_struct_array (ss_arr);
370         }
371
372         public static int test_105_marshal_long_align_struct_array () {
373                 LongAlignStruct[] ss_arr = new LongAlignStruct [2];
374
375                 LongAlignStruct ss = new LongAlignStruct ();
376                 ss.a = 5;
377                 ss.b = 10;
378                 ss.c = 15;
379
380                 ss_arr [0] = ss;
381
382                 ss.a = 20;
383                 ss.b = 25;
384                 ss.c = 30;
385
386                 ss_arr [1] = ss;
387
388                 return mono_test_marshal_long_align_struct_array (ss_arr);
389         }
390
391         /* Test classes as arguments and return values */
392         public static int test_0_marshal_class () {
393                 SimpleClass ss = new  SimpleClass ();
394                 ss.b = true;
395                 ss.d = "TEST";
396                 ss.e = 99;
397                 ss.f = 1.5;
398                 ss.g = 42;
399                 ss.h = 123L;
400
401                 SimpleClass res = mono_test_marshal_class (10, 11, 12, ss, 14);
402                 if (res == null)
403                         return 1;
404                 if  (! (res.a == ss.a && res.b == ss.b && res.c == ss.c && 
405                                 res.d == ss.d && res.e == ss.e && res.f == ss.f &&
406                                 res.g == ss.g && res.h == ss.h))
407                         return 2;
408
409                 /* Test null arguments and results */
410                 res = mono_test_marshal_class (10, 11, 12, null, 14);
411                 if (res != null)
412                         return 3;
413
414                 return 0;
415         }
416
417         public static int test_0_marshal_byref_class () {
418                 SimpleClass ss = new  SimpleClass ();
419                 ss.b = true;
420                 ss.d = "TEST";
421                 ss.e = 99;
422                 ss.f = 1.5;
423                 ss.g = 42;
424                 ss.h = 123L;
425
426                 int res = mono_test_marshal_byref_class (ref ss);
427                 if (ss.d != "TEST-RES")
428                         return 1;
429
430                 return 0;
431         }
432
433         public static int test_0_marshal_delegate () {
434                 SimpleDelegate d = new SimpleDelegate (delegate_test);
435
436                 return mono_test_marshal_delegate (d);
437         }
438
439         public static int test_0_marshal_return_delegate () {
440                 SimpleDelegate d = new SimpleDelegate (delegate_test);
441
442                 SimpleDelegate d2 = mono_test_marshal_return_delegate (d);
443
444                 return d2 (2);
445         }
446
447         public static int test_0_marshal_delegate_struct () {
448                 DelegateStruct s = new DelegateStruct ();
449
450                 s.a = 2;
451                 s.del = new SimpleDelegate (delegate_test);
452                 s.del2 = new SimpleDelegate (delegate_test);
453
454                 DelegateStruct res = mono_test_marshal_delegate_struct (s);
455
456                 if (res.a != 0)
457                         return 1;
458                 if (res.del (2) != 0)
459                         return 2;
460                 if (res.del2 (2) != 0)
461                         return 3;
462
463                 return 0;
464         }
465
466         public static int test_0_marshal_byref_struct () {
467                 SimpleStruct s = new SimpleStruct ();
468                 s.a = true;
469                 s.b = false;
470                 s.c = true;
471                 s.d = "ABC";
472                 s.d2 = "DEF";
473
474                 int res = mono_test_marshal_byref_struct (ref s, true, false, true, "ABC");
475                 if (res != 0)
476                         return 1;
477                 if (s.a != false || s.b != true || s.c != false || s.d != "DEF")
478                         return 2;
479                 return 0;
480         }
481
482         public static int test_0_marshal_byref_struct_in () {
483                 SimpleStruct s = new SimpleStruct ();
484                 s.a = true;
485                 s.b = false;
486                 s.c = true;
487                 s.d = "ABC";
488                 s.d2 = "DEF";
489
490                 int res = mono_test_marshal_byref_struct_in (ref s, true, false, true, "ABC");
491                 if (res != 0)
492                         return 1;
493                 if (s.a != true || s.b != false || s.c != true || s.d != "ABC")
494                         return 2;
495                 return 0;
496         }
497
498         public static int test_0_marshal_byref_struct_inout () {
499                 SimpleStruct s = new SimpleStruct ();
500                 s.a = true;
501                 s.b = false;
502                 s.c = true;
503                 s.d = "ABC";
504                 s.d2 = "DEF";
505
506                 int res = mono_test_marshal_byref_struct_inout (ref s, true, false, true, "ABC");
507                 if (res != 0)
508                         return 1;
509                 if (s.a != false || s.b != true || s.c != false || s.d != "DEF")
510                         return 2;
511                 return 0;
512         }
513
514         public static int test_0_marshal_point () {
515                 Point pt = new Point();
516                 pt.x = 1.25;
517                 pt.y = 3.5;
518                 
519                 return mono_test_marshal_point(pt);
520         }
521
522         public static int test_0_marshal_mixed_point () {
523                 MixedPoint mpt = new MixedPoint();
524                 mpt.x = 5;
525                 mpt.y = 6.75;
526                 
527                 return mono_test_marshal_mixed_point(mpt);
528         }
529
530         public static int test_0_marshal_bool_byref () {
531                 bool b = true;
532                 if (mono_test_marshal_bool_byref (99, ref b, 100) != 1)
533                         return 1;
534                 b = false;
535                 if (mono_test_marshal_bool_byref (99, ref b, 100) != 0)
536                         return 12;
537                 if (b != true)
538                         return 13;
539
540                 return 0;
541         }
542
543         public static int test_0_return_vtype () {
544                 SimpleStruct ss = mono_test_return_vtype (new IntPtr (5));
545
546                 if (!ss.a && ss.b && !ss.c && ss.d == "TEST" && ss.d2 == "TEST2")
547                         return 0;
548
549                 return 1;
550         }
551
552         public static int test_0_marshal_stringbuilder () {
553                 StringBuilder sb = new StringBuilder(255);
554                 sb.Append ("ABCD");
555                 mono_test_marshal_stringbuilder (sb, sb.Capacity);
556                 String res = sb.ToString();
557
558                 if (res != "This is my message.  Isn't it nice?")
559                         return 1;  
560                 
561                 return 0;
562         }
563
564         public static int test_0_marshal_stringbuilder_unicode () {
565                 StringBuilder sb = new StringBuilder(255);
566                 mono_test_marshal_stringbuilder_unicode (sb, sb.Capacity);
567                 String res = sb.ToString();
568
569                 if (res != "This is my message.  Isn't it nice?")
570                         return 1;  
571                 
572                 return 0;
573         }
574
575         public static int test_0_marshal_empty_string_array () {
576                 return mono_test_marshal_empty_string_array (null);
577         }
578
579         public static int test_0_marshal_string_array () {
580                 return mono_test_marshal_string_array (new String [] { "ABC", "DEF" });
581         }
582
583         public static int test_0_marshal_unicode_string_array () {
584                 return mono_test_marshal_unicode_string_array (new String [] { "ABC", "DEF" }, new String [] { "ABC", "DEF" });
585         }
586
587         public static int test_0_marshal_stringbuilder_array () {
588                 StringBuilder sb1 = new StringBuilder ("ABC");
589                 StringBuilder sb2 = new StringBuilder ("DEF");
590
591                 int res = mono_test_marshal_stringbuilder_array (new StringBuilder [] { sb1, sb2 });
592                 if (res != 0)
593                         return res;
594                 if (sb1.ToString () != "DEF")
595                         return 5;
596                 if (sb2.ToString () != "ABC")
597                         return 6;
598                 return 0;
599         }
600
601         public static int test_0_last_error () {
602                 mono_test_last_error (5);
603                 if (Marshal.GetLastWin32Error () == 5)
604                         return 0;
605                 else
606                         return 1;
607         }
608
609         public static int test_0_library_not_found () {
610
611                 try {
612                         mono_entry_point_not_found ();
613                         return 1;
614                 }
615                 catch (EntryPointNotFoundException) {
616                 }
617
618                 return 0;
619         }
620
621         public static int test_0_entry_point_not_found () {
622
623                 try {
624                         mono_library_not_found ();
625                         return 1;
626                 }
627                 catch (DllNotFoundException) {
628                 }
629
630                 return 0;
631         }
632
633         /* Check that the runtime trims .dll from the library name */
634         public static int test_0_trim_dll_from_name () {
635
636                 mono_test_marshal_char_2 ('A');
637
638                 return 0;
639         }
640
641         /* Check that the runtime adds lib to to the library name */
642         public static int test_0_add_lib_to_name () {
643
644                 mono_test_marshal_char_3 ('A');
645
646                 return 0;
647         }
648
649         class C {
650                 public int i;
651         }
652
653         public static int test_0_asany () {
654                 if (mono_test_asany (5, 1) != 0)
655                         return 1;
656
657                 if (mono_test_asany ("ABC", 2) != 0)
658                         return 2;
659
660                 SimpleStruct2 ss2 = new  SimpleStruct2 ();
661                 ss2.b = true;
662                 ss2.d = "TEST";
663                 ss2.e = 99;
664                 ss2.f = 1.5;
665                 ss2.g = 42;
666                 ss2.h = 123L;
667
668                 if (mono_test_asany (ss2, 3) != 0)
669                         return 3;
670
671                 if (mono_test_asany_unicode ("ABC", 4) != 0)
672                         return 4;
673
674                 try {
675                         C c = new C ();
676                         c.i = 5;
677                         mono_test_asany (c, 0);
678                         return 5;
679                 }
680                 catch (ArgumentException) {
681                 }
682
683                 try {
684                         mono_test_asany (new Object (), 0);
685                         return 6;
686                 }
687                 catch (ArgumentException) {
688                 }
689
690                 return 0;
691         }
692
693         /* Byref String Array */
694
695         [DllImport ("libtest", EntryPoint="mono_test_marshal_byref_string_array")]
696         public static extern int mono_test_marshal_byref_string_array (ref string[] data);
697
698         public static int test_0_byref_string_array () {
699
700                 string[] arr = null;
701
702                 if (mono_test_marshal_byref_string_array (ref arr) != 0)
703                         return 1;
704
705                 arr = new string[] { "Alpha", "Beta", "Gamma" };
706
707                 if (mono_test_marshal_byref_string_array (ref arr) != 1)
708                         return 2;
709
710                 /* FIXME: Test returned array and out case */
711
712                 return 0;
713         }
714
715         /*
716          * AMD64 small structs-by-value tests.
717          */
718
719         /* TEST 1: 16 byte long INTEGER struct */
720
721         [StructLayout(LayoutKind.Sequential)]
722         public struct Amd64Struct1 {
723                 public int i;
724                 public int j;
725                 public int k;
726                 public int l;
727         }
728         
729         [DllImport ("libtest", EntryPoint="mono_test_marshal_amd64_pass_return_struct1")]
730         public static extern Amd64Struct1 mono_test_marshal_amd64_pass_return_struct1 (Amd64Struct1 s);
731
732         public static int test_0_amd64_struct1 () {
733                 Amd64Struct1 s = new Amd64Struct1 ();
734                 s.i = 5;
735                 s.j = -5;
736                 s.k = 0xffffff;
737                 s.l = 0xfffffff;
738
739                 Amd64Struct1 s2 = mono_test_marshal_amd64_pass_return_struct1 (s);
740
741                 return ((s2.i == 6) && (s2.j == -4) && (s2.k == 0x1000000) && (s2.l == 0x10000000)) ? 0 : 1;
742         }
743
744         /* TEST 2: 8 byte long INTEGER struct */
745
746         [StructLayout(LayoutKind.Sequential)]
747         public struct Amd64Struct2 {
748                 public int i;
749                 public int j;
750         }
751         
752         [DllImport ("libtest", EntryPoint="mono_test_marshal_amd64_pass_return_struct2")]
753         public static extern Amd64Struct2 mono_test_marshal_amd64_pass_return_struct2 (Amd64Struct2 s);
754
755         public static int test_0_amd64_struct2 () {
756                 Amd64Struct2 s = new Amd64Struct2 ();
757                 s.i = 5;
758                 s.j = -5;
759
760                 Amd64Struct2 s2 = mono_test_marshal_amd64_pass_return_struct2 (s);
761
762                 return ((s2.i == 6) && (s2.j == -4)) ? 0 : 1;
763         }
764
765         /* TEST 3: 4 byte long INTEGER struct */
766
767         [StructLayout(LayoutKind.Sequential)]
768         public struct Amd64Struct3 {
769                 public int i;
770         }
771         
772         [DllImport ("libtest", EntryPoint="mono_test_marshal_amd64_pass_return_struct3")]
773         public static extern Amd64Struct3 mono_test_marshal_amd64_pass_return_struct3 (Amd64Struct3 s);
774
775         public static int test_0_amd64_struct3 () {
776                 Amd64Struct3 s = new Amd64Struct3 ();
777                 s.i = -5;
778
779                 Amd64Struct3 s2 = mono_test_marshal_amd64_pass_return_struct3 (s);
780
781                 return (s2.i == -4) ? 0 : 1;
782         }
783
784         /* Test 4: 16 byte long FLOAT struct */
785
786         [StructLayout(LayoutKind.Sequential)]
787         public struct Amd64Struct4 {
788                 public double d1, d2;
789         }
790         
791         [DllImport ("libtest", EntryPoint="mono_test_marshal_amd64_pass_return_struct4")]
792         public static extern Amd64Struct4 mono_test_marshal_amd64_pass_return_struct4 (Amd64Struct4 s);
793
794         public static int test_0_amd64_struct4 () {
795                 Amd64Struct4 s = new Amd64Struct4 ();
796                 s.d1 = 5.0;
797                 s.d2 = -5.0;
798
799                 Amd64Struct4 s2 = mono_test_marshal_amd64_pass_return_struct4 (s);
800
801                 return (s2.d1 == 6.0 && s2.d2 == -4.0) ? 0 : 1;
802         }
803
804         /*
805          * IA64 struct tests
806          */
807
808         /* Test 5: Float HFA */
809
810         [StructLayout(LayoutKind.Sequential)]
811         public struct TestStruct5 {
812                 public float d1, d2;
813         }
814         
815         [DllImport ("libtest", EntryPoint="mono_test_marshal_ia64_pass_return_struct5")]
816         public static extern TestStruct5 mono_test_marshal_ia64_pass_return_struct5 (double d1, double d2, TestStruct5 s, double f3, double f4);
817
818         public static int test_0_ia64_struct5 () {
819                 TestStruct5 s = new TestStruct5 ();
820                 s.d1 = 5.0f;
821                 s.d2 = -5.0f;
822
823                 TestStruct5 s2 = mono_test_marshal_ia64_pass_return_struct5 (1.0, 2.0, s, 3.0, 4.0);
824
825                 return (s2.d1 == 8.0 && s2.d2 == 2.0) ? 0 : 1;
826         }
827
828         /* Test 6: Double HFA */
829
830         [StructLayout(LayoutKind.Sequential)]
831         public struct TestStruct6 {
832                 public double d1, d2;
833         }
834         
835         [DllImport ("libtest", EntryPoint="mono_test_marshal_ia64_pass_return_struct6")]
836         public static extern TestStruct6 mono_test_marshal_ia64_pass_return_struct6 (double d1, double d2, TestStruct6 s, double f3, double f4);
837
838         public static int test_0_ia64_struct6 () {
839                 TestStruct6 s = new TestStruct6 ();
840                 s.d1 = 6.0;
841                 s.d2 = -6.0;
842
843                 TestStruct6 s2 = mono_test_marshal_ia64_pass_return_struct6 (1.0, 2.0, s, 3.0, 4.0);
844
845                 return (s2.d1 == 9.0 && s2.d2 == 1.0) ? 0 : 1;
846         }
847         
848         /* Blittable class */
849         [DllImport("libtest")]
850         private static extern VectorList TestVectorList (VectorList vl);
851
852         public static int test_0_marshal_blittable_class () {
853                 VectorList v1 = new VectorList ();
854
855                 /* Since it is blittable, it looks like it is passed as in/out */
856                 VectorList v2 = TestVectorList (v1);
857
858                 if (v1.a != 2 || v1.b != 3)
859                         return 1;
860                 
861                 if (v2.a != 2 || v2.b != 3)
862                         return 2;
863                 
864                 return 0;
865         }
866
867         public static int test_0_marshal_byval_class () {
868                 SimpleObj obj0 = new SimpleObj ();
869                 obj0.str = "T1";
870                 obj0.i = 4;
871                 
872                 if (class_marshal_test0 (obj0) != 0)
873                         return 1;
874
875                 return 0;
876         }
877
878         public static int test_0_marshal_byval_class_null () {
879                 if (class_marshal_test4 (null) != 0)
880                         return 1;
881
882                 return 0;
883         }
884
885         public static int test_0_marshal_out_class () {
886                 SimpleObj obj1;
887
888                 class_marshal_test1 (out obj1);
889
890                 if (obj1.str != "ABC")
891                         return 1;
892
893                 if (obj1.i != 5)
894                         return 2;
895
896                 return 0;
897         }
898
899         public static int test_0_marshal_string () {
900                 return string_marshal_test0 ("TEST0");
901         }
902
903         public static int test_0_marshal_out_string () {
904                 string res;
905                 
906                 string_marshal_test1 (out res);
907
908                 if (res != "TEST1")
909                         return 1;
910
911                 return 0;
912         }
913
914         public static int test_0_marshal_byref_string () {
915                 string res = "TEST1";
916
917                 return string_marshal_test2 (ref res);
918         }
919
920         public static int test_0_marshal_null_string () {
921                 return string_marshal_test3 (null);
922         }
923
924         [DllImport ("libtest", EntryPoint="mono_test_stdcall_name_mangling", CallingConvention=CallingConvention.StdCall)]
925         public static extern int mono_test_stdcall_name_mangling (int a, int b, int c);
926
927         public static int test_0_stdcall_name_mangling () {
928                 return mono_test_stdcall_name_mangling (0, 1, 2) == 3 ? 0 : 1;
929         }
930
931         /*
932          * Pointers to structures can not be passed
933          */
934
935         public struct CharInfo {
936                 public char Character;
937                 public short Attributes;
938         }
939
940         [DllImport ("libtest", EntryPoint="mono_test_marshal_struct")]
941         public static unsafe extern int mono_test_marshal_ptr_to_struct (CharInfo *ptr);
942
943         public static unsafe int test_0_marshal_ptr_to_struct () {
944                 CharInfo [] buffer = new CharInfo [1];
945                 fixed (CharInfo *ptr = &buffer [0]) {
946                         try {
947                                 mono_test_marshal_ptr_to_struct (ptr);
948                                 return 1;
949                         }
950                         catch (MarshalDirectiveException) {
951                                 return 0;
952                         }
953                 }
954                 return 1;
955         }
956
957         /*
958          * LPWStr marshalling
959          */
960
961         [DllImport("libtest", EntryPoint="test_lpwstr_marshal")]
962         [return: MarshalAs(UnmanagedType.LPWStr)]
963         private static extern string mono_test_marshal_lpwstr_marshal(
964                 [MarshalAs(UnmanagedType.LPWStr)] string s,
965                 int length );
966
967         [DllImport("libtest", EntryPoint="test_lpwstr_marshal", CharSet=CharSet.Unicode)]
968         private static extern string mono_test_marshal_lpwstr_marshal2(
969                 string s,
970                 int length );
971
972         public static int test_0_pass_return_lwpstr () {
973                 string s = "ABC";
974                 
975                 string res = mono_test_marshal_lpwstr_marshal (s, s.Length);
976
977                 if (res != "ABC")
978                         return 1;
979
980                 string res2 = mono_test_marshal_lpwstr_marshal2 (s, s.Length);
981
982                 if (res2 != "ABC")
983                         return 2;
984                 
985                 return 0;               
986         }
987
988         /*
989          * Byref bool marshalling
990          */
991
992         [DllImport("libtest")]
993         extern static int marshal_test_ref_bool
994         (
995                 int i, 
996                 [MarshalAs(UnmanagedType.I1)] ref bool b1, 
997                 [MarshalAs(UnmanagedType.VariantBool)] ref bool b2, 
998                 ref bool b3
999         );
1000
1001         public static int test_0_pass_byref_bool () {
1002                 for (int i = 0; i < 8; i++)
1003                 {
1004                         bool b1 = (i & 4) != 0;
1005                         bool b2 = (i & 2) != 0;
1006                         bool b3 = (i & 1) != 0;
1007                         bool orig_b1 = b1, orig_b2 = b2, orig_b3 = b3;
1008                         if (marshal_test_ref_bool(i, ref b1, ref b2, ref b3) != 0)
1009                                 return 4 * i + 1;
1010                         if (b1 != !orig_b1)
1011                                 return 4 * i + 2;
1012                         if (b2 != !orig_b2)
1013                                 return 4 * i + 3;
1014                         if (b3 != !orig_b3)
1015                                 return 4 * i + 4;
1016                 }
1017
1018                 return 0;
1019         }
1020
1021         /*
1022          * Bool struct field marshalling
1023          */
1024
1025         struct BoolStruct
1026         {
1027                 public int i;
1028                 [MarshalAs(UnmanagedType.I1)] public bool b1;
1029                 [MarshalAs(UnmanagedType.VariantBool)] public bool b2;
1030                 public bool b3;
1031         }
1032
1033         [DllImport("libtest")]
1034         extern static int marshal_test_bool_struct(ref BoolStruct s);
1035
1036         public static int test_0_pass_bool_in_struct () {
1037                 for (int i = 0; i < 8; i++)
1038                 {
1039                         BoolStruct s = new BoolStruct();
1040                         s.i = i;
1041                         s.b1 = (i & 4) != 0;
1042                         s.b2 = (i & 2) != 0;
1043                         s.b3 = (i & 1) != 0;
1044                         BoolStruct orig = s;
1045                         if (marshal_test_bool_struct(ref s) != 0)
1046                                 return 4 * i + 33;
1047                         if (s.b1 != !orig.b1)
1048                                 return 4 * i + 34;
1049                         if (s.b2 != !orig.b2)
1050                                 return 4 * i + 35;
1051                         if (s.b3 != !orig.b3)
1052                                 return 4 * i + 36;
1053                 }
1054
1055                 return 0;
1056         }
1057
1058         /*
1059          * Invoking pinvoke methods through delegates
1060          */
1061
1062         delegate int MyDelegate (string name);
1063
1064         [DllImport ("libtest", EntryPoint="mono_test_puts_static")]
1065         public static extern int puts_static (string name);
1066
1067         public static int test_0_invoke_pinvoke_through_delegate () {
1068                 puts_static ("A simple Test for PInvoke 1");
1069
1070                 MyDelegate d = new MyDelegate (puts_static);
1071                 d ("A simple Test for PInvoke 2");
1072
1073                 object [] args = {"A simple Test for PInvoke 3"};
1074                 d.DynamicInvoke (args);
1075
1076                 return 0;
1077         }
1078
1079         /*
1080          * Missing virtual pinvoke methods
1081          */
1082
1083         public class T {
1084
1085                 public virtual object MyClone ()
1086                 {
1087                         return null;
1088                 }
1089         }
1090
1091         public class T2 : T {
1092                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1093                 public override extern object MyClone ();
1094         }
1095
1096         public static int test_0_missing_virtual_pinvoke_method () {
1097                 T2 t = new T2 ();
1098
1099                 try {
1100                         t.MyClone ();
1101                 } catch (Exception ex) {
1102                         return 0;
1103                 }
1104                 
1105                 return 1;
1106         }
1107 }
1108