[xbuild] Evaluate Import with MSBuildThisFile* properties set.
[mono.git] / mono / tests / pinvoke2.cs
index a9147a0a3d8e2c6a1225b04fc2292c9c258860c0..4c19f359f30d9c94410631f12baa028836cdfd31 100644 (file)
@@ -2,9 +2,12 @@ using System;
 using System.Text;
 using System.Runtime.InteropServices;
 using System.Runtime.CompilerServices;
+using System.Reflection.Emit;
 
 public class Tests {
 
+       public int int_field;
+
        public static int delegate_test (int a)
        {
                if (a == 2)
@@ -12,6 +15,11 @@ public class Tests {
 
                return 1;
        }
+
+       public int delegate_test_instance (int a)
+       {
+               return int_field + a;
+       }
        
        [StructLayout (LayoutKind.Sequential)]
        public struct SimpleStruct {
@@ -23,6 +31,16 @@ public class Tests {
                public string d2;
        }
 
+       [StructLayout (LayoutKind.Sequential)]
+       public struct SimpleStructGen<T> {
+               public bool a;
+               public bool b;
+               public bool c;
+               public string d;
+               [MarshalAs(UnmanagedType.LPWStr)]
+               public string d2;
+       }
+
        [StructLayout (LayoutKind.Sequential)]
        public struct SimpleStruct2 {
                public bool a;
@@ -45,6 +63,8 @@ public class Tests {
                public SimpleDelegate del;
                [MarshalAs(UnmanagedType.FunctionPtr)] 
                public SimpleDelegate del2;
+               [MarshalAs(UnmanagedType.FunctionPtr)] 
+               public SimpleDelegate del3;
        }
 
        /* sparcv9 has complex conventions when passing structs with doubles in them 
@@ -150,6 +170,24 @@ public class Tests {
        [DllImport ("libtest", EntryPoint="mono_test_marshal_bool_byref")]
        public static extern int mono_test_marshal_bool_byref (int a, ref bool b, int c);
 
+       [DllImport ("libtest", EntryPoint="mono_test_marshal_bool_in_as_I1_U1")]
+       public static extern int mono_test_marshal_bool_in_as_I1 ([MarshalAs (UnmanagedType.I1)] bool bTrue, [MarshalAs (UnmanagedType.I1)] bool bFalse);
+
+       [DllImport ("libtest", EntryPoint="mono_test_marshal_bool_in_as_I1_U1")]
+       public static extern int mono_test_marshal_bool_in_as_U1 ([MarshalAs (UnmanagedType.U1)] bool bTrue, [MarshalAs (UnmanagedType.U1)] bool bFalse);
+
+       [DllImport ("libtest", EntryPoint="mono_test_marshal_bool_out_as_I1_U1")]
+       public static extern int mono_test_marshal_bool_out_as_I1 ([MarshalAs (UnmanagedType.I1)] out bool bTrue, [MarshalAs (UnmanagedType.I1)] out bool bFalse);
+
+       [DllImport ("libtest", EntryPoint="mono_test_marshal_bool_out_as_I1_U1")]
+       public static extern int mono_test_marshal_bool_out_as_U1 ([MarshalAs (UnmanagedType.U1)] out bool bTrue, [MarshalAs (UnmanagedType.U1)] out bool bFalse);
+
+       [DllImport ("libtest", EntryPoint="mono_test_marshal_bool_ref_as_I1_U1")]
+       public static extern int mono_test_marshal_bool_ref_as_I1 ([MarshalAs (UnmanagedType.I1)] ref bool bTrue, [MarshalAs (UnmanagedType.I1)] ref bool bFalse);
+
+       [DllImport ("libtest", EntryPoint="mono_test_marshal_bool_ref_as_I1_U1")]
+       public static extern int mono_test_marshal_bool_ref_as_U1 ([MarshalAs (UnmanagedType.U1)] ref bool bTrue, [MarshalAs (UnmanagedType.U1)] ref bool bFalse);
+
        [DllImport ("libtest", EntryPoint="mono_test_marshal_array")]
        public static extern int mono_test_marshal_array (int [] a1);
 
@@ -176,6 +214,9 @@ public class Tests {
        
        [DllImport ("libtest", EntryPoint="mono_test_marshal_struct")]
        public static extern int mono_test_marshal_struct (SimpleStruct ss);
+       
+       [DllImport ("libtest", EntryPoint="mono_test_marshal_struct")]
+       public static extern int mono_test_marshal_struct_gen (SimpleStructGen<string> ss);
 
        [DllImport ("libtest", EntryPoint="mono_test_marshal_struct2")]
        public static extern int mono_test_marshal_struct2 (SimpleStruct2 ss);
@@ -240,6 +281,12 @@ public class Tests {
        [DllImport ("libtest", EntryPoint="mono_test_marshal_stringbuilder_unicode", CharSet=CharSet.Unicode)]
        public static extern void mono_test_marshal_stringbuilder_unicode (StringBuilder sb, int len);
 
+       [DllImport ("libtest", EntryPoint="mono_test_marshal_stringbuilder_out")]
+       public static extern void mono_test_marshal_stringbuilder_out (out StringBuilder sb);
+
+       [DllImport ("libtest", EntryPoint="mono_test_marshal_stringbuilder_out_unicode", CharSet=CharSet.Unicode)]
+       public static extern void mono_test_marshal_stringbuilder_out_unicode (out StringBuilder sb);
+
        [DllImport ("libtest", EntryPoint="mono_test_last_error", SetLastError=true)]
        public static extern void mono_test_last_error (int err);
 
@@ -249,10 +296,10 @@ public class Tests {
        [DllImport ("libtest", EntryPoint="mono_test_asany", CharSet=CharSet.Unicode)]
        public static extern int mono_test_asany_unicode ([MarshalAs (UnmanagedType.AsAny)] object o, int what);
 
-       [DllImport("libtest", EntryPoint="mono_test_marshal_asany_inout")]
+       [DllImport("libtest", EntryPoint="mono_test_marshal_asany_in")]
        static extern void mono_test_asany_in ([MarshalAs(UnmanagedType.AsAny)][In] object obj); 
 
-       [DllImport("libtest", EntryPoint="mono_test_marshal_asany_inout")]
+       [DllImport("libtest", EntryPoint="mono_test_marshal_asany_out")]
        static extern void mono_test_asany_out ([MarshalAs(UnmanagedType.AsAny)][Out] object obj); 
        [DllImport("libtest", EntryPoint="mono_test_marshal_asany_inout")]
        static extern void mono_test_asany_inout ([MarshalAs(UnmanagedType.AsAny)][In, Out] object obj); 
@@ -359,6 +406,14 @@ public class Tests {
                return mono_test_marshal_struct (ss);
        }
 
+       public static int test_0_marshal_struct_gen () {
+               SimpleStructGen<string> ss = new  SimpleStructGen<string> ();
+               ss.b = true;
+               ss.d = "TEST";
+               
+               return mono_test_marshal_struct_gen (ss);
+       }
+
        public static int test_0_marshal_struct2 () {
                SimpleStruct2 ss2 = new  SimpleStruct2 ();
                ss2.b = true;
@@ -500,6 +555,27 @@ public class Tests {
                return mono_test_marshal_delegate (d);
        }
 
+       public static int test_34_marshal_instance_delegate () {
+               Tests t = new Tests ();
+               t.int_field = 32;
+               SimpleDelegate d = new SimpleDelegate (t.delegate_test_instance);
+
+               return mono_test_marshal_delegate (d);
+       }
+
+       /* Static delegates closed over their first argument */
+       public static int closed_delegate (Tests t, int a) {
+               return t.int_field + a;
+       }
+
+       public static int test_34_marshal_closed_static_delegate () {
+               Tests t = new Tests ();
+               t.int_field = 32;
+               SimpleDelegate d = (SimpleDelegate)Delegate.CreateDelegate (typeof (SimpleDelegate), t, typeof (Tests).GetMethod ("closed_delegate"));
+
+               return mono_test_marshal_delegate (d);
+       }
+
        public static int test_0_marshal_return_delegate () {
                SimpleDelegate d = new SimpleDelegate (delegate_test);
 
@@ -514,6 +590,7 @@ public class Tests {
                s.a = 2;
                s.del = new SimpleDelegate (delegate_test);
                s.del2 = new SimpleDelegate (delegate_test);
+               s.del3 = null;
 
                DelegateStruct res = mono_test_marshal_delegate_struct (s);
 
@@ -523,10 +600,23 @@ public class Tests {
                        return 2;
                if (res.del2 (2) != 0)
                        return 3;
+               if (res.del3 != null)
+                       return 4;
 
                return 0;
        }
 
+       [DllImport ("libtest", EntryPoint="mono_test_marshal_out_delegate")]
+       public static extern int mono_test_marshal_out_delegate (out SimpleDelegate d);
+
+       public static int test_3_marshal_out_delegate () {
+               SimpleDelegate d = null;
+
+               mono_test_marshal_out_delegate (out d);
+
+               return d (2);
+       }
+
        public static int test_0_marshal_byref_struct () {
                SimpleStruct s = new SimpleStruct ();
                s.a = true;
@@ -604,6 +694,62 @@ public class Tests {
                return 0;
        }
 
+       public static int test_0_marshal_bool_as_I1 () {
+
+               int ret;
+               bool bTrue, bFalse;
+               if ((ret = mono_test_marshal_bool_in_as_I1 (true, false)) != 0)
+                       return ret;
+
+               if ((ret = mono_test_marshal_bool_out_as_I1 (out bTrue, out bFalse)) != 0)
+                       return ret;
+
+               if(!bTrue)
+                       return 10;
+
+               if(bFalse)
+                       return 11;
+
+               if ((ret = mono_test_marshal_bool_ref_as_I1 (ref bTrue, ref bFalse)) != 0)
+                       return ret;
+
+               if(bTrue)
+                       return 12;
+
+               if(!bFalse)
+                       return 13;
+
+               return 0;
+       }
+
+       public static int test_0_marshal_bool_as_U1 () {
+
+               int ret;
+               bool bTrue, bFalse;
+               if ((ret = mono_test_marshal_bool_in_as_U1 (true, false)) != 0)
+                       return ret;
+
+               if ((ret = mono_test_marshal_bool_out_as_U1 (out bTrue, out bFalse)) != 0)
+                       return ret;
+
+               if(!bTrue)
+                       return 10;
+
+               if(bFalse)
+                       return 11;
+
+               if ((ret = mono_test_marshal_bool_ref_as_U1 (ref bTrue, ref bFalse)) != 0)
+                       return ret;
+
+               if(bTrue)
+                       return 12;
+
+               if(!bFalse)
+                       return 13;
+
+               return 0;
+       }
+
        public static int test_0_return_vtype () {
                SimpleStruct ss = mono_test_return_vtype (new IntPtr (5));
 
@@ -648,6 +794,24 @@ public class Tests {
                return 0;
        }
 
+       public static int test_0_marshal_stringbuilder_out () {
+               StringBuilder sb;
+               mono_test_marshal_stringbuilder_out (out sb);
+               
+               if (sb.ToString () != "This is my message.  Isn't it nice?")
+                       return 1;  
+               return 0;
+       }
+
+       public static int test_0_marshal_stringbuilder_out_unicode () {
+               StringBuilder sb;
+               mono_test_marshal_stringbuilder_out_unicode (out sb);
+
+               if (sb.ToString () != "This is my message.  Isn't it nice?")
+                       return 1;  
+               return 0;
+       }
+
        public static int test_0_marshal_empty_string_array () {
                return mono_test_marshal_empty_string_array (null);
        }
@@ -682,7 +846,7 @@ public class Tests {
                        return 1;
        }
 
-       public static int test_0_library_not_found () {
+       public static int test_0_entry_point_not_found () {
 
                try {
                        mono_entry_point_not_found ();
@@ -694,7 +858,7 @@ public class Tests {
                return 0;
        }
 
-       public static int test_0_entry_point_not_found () {
+       public static int test_0_library_not_found () {
 
                try {
                        mono_library_not_found ();
@@ -869,6 +1033,9 @@ public class Tests {
        
        [DllImport ("libtest", EntryPoint="mono_test_marshal_amd64_pass_return_struct1")]
        public static extern Amd64Struct1 mono_test_marshal_amd64_pass_return_struct1 (Amd64Struct1 s);
+       
+       [DllImport ("libtest", EntryPoint="mono_test_marshal_amd64_pass_return_struct1_many_args")]
+       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);
 
        public static int test_0_amd64_struct1 () {
                Amd64Struct1 s = new Amd64Struct1 ();
@@ -882,6 +1049,18 @@ public class Tests {
                return ((s2.i == 6) && (s2.j == -4) && (s2.k == 0x1000000) && (s2.l == 0x10000000)) ? 0 : 1;
        }
 
+       public static int test_0_amd64_struct1_many_args () {
+               Amd64Struct1 s = new Amd64Struct1 ();
+               s.i = 5;
+               s.j = -5;
+               s.k = 0xffffff;
+               s.l = 0xfffffff;
+
+               Amd64Struct1 s2 = mono_test_marshal_amd64_pass_return_struct1_many_args (s, 1, 2, 3, 4, 5, 6, 7, 8);
+
+               return ((s2.i == 6) && (s2.j == -4) && (s2.k == 0x1000000) && (s2.l == 0x10000000 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8)) ? 0 : 1;
+       }
+
        /* TEST 2: 8 byte long INTEGER struct */
 
        [StructLayout(LayoutKind.Sequential)]
@@ -954,16 +1133,16 @@ public class Tests {
        }
        
        [DllImport ("libtest", EntryPoint="mono_test_marshal_ia64_pass_return_struct5")]
-       public static extern TestStruct5 mono_test_marshal_ia64_pass_return_struct5 (double d1, double d2, TestStruct5 s, double f3, double f4);
+       public static extern TestStruct5 mono_test_marshal_ia64_pass_return_struct5 (double d1, double d2, TestStruct5 s, int i, double f3, double f4);
 
        public static int test_0_ia64_struct5 () {
                TestStruct5 s = new TestStruct5 ();
                s.d1 = 5.0f;
                s.d2 = -5.0f;
 
-               TestStruct5 s2 = mono_test_marshal_ia64_pass_return_struct5 (1.0, 2.0, s, 3.0, 4.0);
+               TestStruct5 s2 = mono_test_marshal_ia64_pass_return_struct5 (1.0, 2.0, s, 5, 3.0, 4.0);
 
-               return (s2.d1 == 8.0 && s2.d2 == 2.0) ? 0 : 1;
+               return (s2.d1 == 13.0 && s2.d2 == 7.0) ? 0 : 1;
        }
 
        /* Test 6: Double HFA */
@@ -974,16 +1153,16 @@ public class Tests {
        }
        
        [DllImport ("libtest", EntryPoint="mono_test_marshal_ia64_pass_return_struct6")]
-       public static extern TestStruct6 mono_test_marshal_ia64_pass_return_struct6 (double d1, double d2, TestStruct6 s, double f3, double f4);
+       public static extern TestStruct6 mono_test_marshal_ia64_pass_return_struct6 (double d1, double d2, TestStruct6 s, int i, double f3, double f4);
 
        public static int test_0_ia64_struct6 () {
                TestStruct6 s = new TestStruct6 ();
                s.d1 = 6.0;
                s.d2 = -6.0;
 
-               TestStruct6 s2 = mono_test_marshal_ia64_pass_return_struct6 (1.0, 2.0, s, 3.0, 4.0);
+               TestStruct6 s2 = mono_test_marshal_ia64_pass_return_struct6 (1.0, 2.0, s, 3, 4.0, 5.0);
 
-               return (s2.d1 == 9.0 && s2.d2 == 1.0) ? 0 : 1;
+               return (s2.d1 == 12.0 && s2.d2 == 3.0) ? 0 : 1;
        }
        
        /* Blittable class */
@@ -1011,6 +1190,37 @@ public class Tests {
                return 0;
        }
 
+       /*
+        * Generic structures
+        */
+
+       [StructLayout(LayoutKind.Sequential)]
+       public struct Amd64Struct1Gen<T> {
+               public T i;
+               public T j;
+               public T k;
+               public T l;
+       }
+       
+       [DllImport ("libtest", EntryPoint="mono_test_marshal_amd64_pass_return_struct1")]
+       public static extern Amd64Struct1Gen<int> mono_test_marshal_amd64_pass_return_struct1_gen (Amd64Struct1Gen<int> s);
+
+       public static int test_0_amd64_struct1_gen () {
+               Amd64Struct1Gen<int> s = new Amd64Struct1Gen<int> ();
+               s.i = 5;
+               s.j = -5;
+               s.k = 0xffffff;
+               s.l = 0xfffffff;
+
+               Amd64Struct1Gen<int> s2 = mono_test_marshal_amd64_pass_return_struct1_gen (s);
+
+               return ((s2.i == 6) && (s2.j == -4) && (s2.k == 0x1000000) && (s2.l == 0x10000000)) ? 0 : 1;
+       }
+
+       /*
+        * Other tests
+        */
+
        public static int test_0_marshal_byval_class () {
                SimpleObj obj0 = new SimpleObj ();
                obj0.str = "T1";
@@ -1075,6 +1285,17 @@ public class Tests {
                return mono_test_stdcall_name_mangling (0, 1, 2) == 3 ? 0 : 1;
        }
 
+       /* Float test */
+
+       [DllImport ("libtest", EntryPoint="mono_test_marshal_pass_return_float")]
+       public static extern float mono_test_marshal_pass_return_float (float f);
+
+       public static int test_0_pass_return_float () {
+               float f = mono_test_marshal_pass_return_float (1.5f);
+
+               return (f == 2.5f) ? 0 : 1;
+       }
+
        /*
         * Pointers to structures can not be passed
         */
@@ -1116,7 +1337,32 @@ public class Tests {
                string s,
                int length );
 
+       [DllImport("libtest", EntryPoint="test_lpwstr_marshal_out")]
+       private static extern void mono_test_marshal_lpwstr_out_marshal(
+               [MarshalAs(UnmanagedType.LPWStr)] out string s);
+
+       [DllImport("libtest", EntryPoint="test_lpwstr_marshal_out", CharSet=CharSet.Unicode)]
+       private static extern void mono_test_marshal_lpwstr_out_marshal2(
+               out string s);
+
        public static int test_0_pass_return_lwpstr () {
+               string s;
+               
+               mono_test_marshal_lpwstr_out_marshal (out s);
+
+               if (s != "ABC")
+                       return 1;
+
+               s = null;
+               mono_test_marshal_lpwstr_out_marshal2 (out s);
+
+               if (s != "ABC")
+                       return 2;
+               
+               return 0;               
+       }
+
+       public static int test_0_out_lwpstr () {
                string s = "ABC";
                
                string res = mono_test_marshal_lpwstr_marshal (s, s.Length);
@@ -1202,6 +1448,31 @@ public class Tests {
                return 0;
        }
 
+       /*
+        * Alignment of structs containing longs
+        */
+
+       struct LongStruct2 {
+               public long l;
+       }
+
+       struct LongStruct {
+               public int i;
+               public LongStruct2 l;
+       }
+
+       [DllImport("libtest")]
+       extern static int mono_test_marshal_long_struct (ref LongStruct s);
+
+       public static int test_47_pass_long_struct () {
+               LongStruct s = new LongStruct ();
+               s.i = 5;
+               s.l = new LongStruct2 ();
+               s.l.l = 42;
+
+               return mono_test_marshal_long_struct (ref s);
+       }
+
        /*
         * Invoking pinvoke methods through delegates
         */
@@ -1251,5 +1522,122 @@ public class Tests {
                
                return 1;
        }
+
+       /*
+        * Marshalling of type 'object'
+        */
+
+       [DllImport ("libtest", EntryPoint="mono_test_marshal_class")]
+       public static extern SimpleClass mono_test_marshal_object (int i, int j, int k, object ss, int l);
+
+       public static int test_0_marshal_object () {
+               try {
+                       mono_test_marshal_object (0, 0, 0, null, 0);
+                       return 1;
+               } catch (Exception) {
+                       return 0;
+               }
+       }
+
+       /*
+        * Marshalling of DateTime to OLE DATE (double)
+        */
+       [DllImport ("libtest", EntryPoint="mono_test_marshal_date_time")]
+       public static extern double mono_test_marshal_date_time (DateTime d, out DateTime d2);
+
+       public static int test_0_marshal_date_time () {
+               DateTime d = new DateTime (2009, 12, 6);
+               DateTime d2;
+               double d3 = mono_test_marshal_date_time (d, out d2);
+               if (d3 != 40153.0)
+                       return 1;
+               if (d2 != d)
+                       return 2;
+               return 0;
+       }
+
+       /*
+        * Calling pinvoke functions dynamically using calli
+        */
+       
+       [DllImport("libtest")]
+       private static extern IntPtr mono_test_marshal_lookup_symbol (string fileName);
+
+       delegate void CalliDel (IntPtr a, int[] f);
+
+       public static int test_0_calli_dynamic () {
+               /* we need the cdecl version because the icall convention demands it under Windows */
+               IntPtr func = mono_test_marshal_lookup_symbol ("mono_test_marshal_inout_array_cdecl");
+
+               DynamicMethod dm = new DynamicMethod ("calli", typeof (void), new Type [] { typeof (IntPtr), typeof (int[]) });
+
+               var il = dm.GetILGenerator ();
+               var signature = SignatureHelper.GetMethodSigHelper (CallingConvention.Cdecl, typeof (void));
+
+               il.Emit (OpCodes.Ldarg, 1);
+               signature.AddArgument (typeof (byte[]));
+
+               il.Emit (OpCodes.Ldarg_0);
+
+               il.Emit (OpCodes.Calli, signature);
+               il.Emit (OpCodes.Ret);
+
+               var f = (CalliDel)dm.CreateDelegate (typeof (CalliDel));
+
+               int[] arr = new int [1000];
+               for (int i = 0; i < 50; ++i)
+                       arr [i] = (int)i;
+               f (func, arr);
+               if (arr.Length != 1000)
+                       return 1;
+               for (int i = 0; i < 50; ++i)
+                       if (arr [i] != 50 - i)
+                               return 2;
+
+               return 0;
+       }
+
+
+       /*char array marshaling */
+       [DllImport ("libtest", EntryPoint="mono_test_marshal_ansi_char_array", CharSet=CharSet.Ansi)]
+       public static extern int mono_test_marshal_ansi_char_array (char[] a1);
+
+       public static int test_0_marshal_ansi_char_array () {
+               char[] buf = new char [32];
+               buf [0] = 'q';
+               buf [1] = 'w';
+               buf [2] = 'e';
+               buf [3] = 'r';
+
+               if (mono_test_marshal_ansi_char_array (buf) != 0)
+                       return 1;
+
+               string s = new string (buf);
+               if (s.StartsWith ("qwer"))
+                       return 0;
+               else
+                       return 2;
+       }
+
+       /*char array marshaling */
+       [DllImport ("libtest", EntryPoint="mono_test_marshal_unicode_char_array", CharSet=CharSet.Unicode)]
+       public static extern int mono_test_marshal_unicode_char_array (char[] a1);
+
+       public static int test_0_marshal_unicode_char_array () {
+               char[] buf = new char [32];
+               buf [0] = 'q';
+               buf [1] = 'w';
+               buf [2] = 'e';
+               buf [3] = 'r';
+
+               if (mono_test_marshal_unicode_char_array (buf) != 0)
+                       return 1;
+
+               string s = new string (buf);
+               if (s.StartsWith ("abcdef"))
+                       return 0;
+               else
+                       return 2;
+       }
 }