2002-07-16 Dietmar Maurer <dietmar@ximian.com>
authorDietmar Maurer <dietmar@mono-cvs.ximian.com>
Tue, 16 Jul 2002 08:18:51 +0000 (08:18 -0000)
committerDietmar Maurer <dietmar@mono-cvs.ximian.com>
Tue, 16 Jul 2002 08:18:51 +0000 (08:18 -0000)
* marshal.c (mono_marshal_get_native_wrapper): support valuetypes

* jit.c (mono_analyze_stack): adjust valuetype size for pinvoke calls

svn path=/trunk/mono/; revision=5822

mono/jit/ChangeLog
mono/jit/jit.c
mono/jit/x86.brg
mono/metadata/ChangeLog
mono/metadata/marshal.c
mono/metadata/metadata.h
mono/tests/Makefile.am
mono/tests/libtest.c
mono/tests/marshal2.cs
mono/tests/pinvoke2.cs [new file with mode: 0755]
mono/tests/pinvoke3.cs [new file with mode: 0755]

index d29cd8f9fb7061bcda7c2b1d2c595e6ee8845509..d210e60329f11d9d3f8cce49d1fc1b5bc88897e3 100644 (file)
@@ -1,4 +1,8 @@
-2002-07-11  Dietmar Maurer  <dietmar@ximian.com>
+2002-07-16  Dietmar Maurer  <dietmar@ximian.com>
+
+       * jit.c (mono_analyze_stack): adjust valuetype size for pinvoke calls
+
+i2002-07-11  Dietmar Maurer  <dietmar@ximian.com>
 
        * x86.brg (freg): new rule freg: CALL_R8 (this, reg)
 
index 1eee8aec47dc6f59940c6ebd73fa1f70b4c4caae..d818c6e5cf97c0cdb6c6f5d7aa1341d07e1ded1c 100644 (file)
@@ -2141,7 +2141,11 @@ mono_analyze_stack (MonoFlowGraph *cfg)
                        for (k = nargs - 1; k >= 0; k--) {
                                MonoType *type = csig->params [k];
                                t1 = mono_ctree_new (mp, mono_map_arg_type (type), arg_sp [k], NULL);
-                               size = mono_type_stack_size (type, &align);
+                               if (csig->pinvoke && ISSTRUCT (type)) {
+                                       size = mono_class_native_size (type->data.klass);
+                               } else {
+                                       size = mono_type_stack_size (type, &align);
+                               }
                                t1->data.i = size;
                                ADD_TREE (t1, cli_addr);
                                args_size += size;
@@ -3615,8 +3619,7 @@ mono_jit_compile_method (MonoMethod *method)
        mono_jit_stats.methods_compiled++;
        
        if (mono_jit_trace_calls || mono_jit_dump_asm || mono_jit_dump_forest) {
-               printf ("Start JIT compilation of %s.%s:%s\n", method->klass->name_space,
-                       method->klass->name, method->name);
+               printf ("Start JIT compilation of %s\n", mono_method_full_name (method, TRUE));
        }
 
        if (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) {
@@ -3625,8 +3628,7 @@ mono_jit_compile_method (MonoMethod *method)
                        if (mono_debug_format != MONO_DEBUG_FORMAT_NONE) 
                                return NULL;
 
-                       g_error ("Don't know how to exec runtime method %s.%s::%s", 
-                                method->klass->name_space, method->klass->name, method->name);
+                       g_error ("Don't know how to exec runtime method %s", mono_method_full_name (method, TRUE));
                }
        } else {
                MonoMethodHeader *header = ((MonoMethodNormal *)method)->header;
@@ -3727,8 +3729,7 @@ mono_jit_compile_method (MonoMethod *method)
        }
 
        if (mono_jit_trace_calls || mono_jit_dump_asm || mono_jit_dump_forest) {
-               printf ("END JIT compilation of %s.%s:%s %p %p\n", method->klass->name_space,
-                       method->klass->name, method->name, method, addr);
+               printf ("END JIT compilation of %s %p %p\n", mono_method_full_name (method, FALSE), method, addr);
        }
 
        g_hash_table_insert (jit_code_hash, method, addr);
index ef6dace948819dd5235ea4bde3d5c71ac94a46d1..a2a3eab7d51d8951087631cdc1fa1ed714a60cfa 100644 (file)
@@ -159,7 +159,7 @@ void *
 debug_memcopy (void *dest, const void *src, size_t n);
 
 #ifdef DEBUG
-#define MEMCOPY debug_memcpy
+#define MEMCOPY debug_memcopy
 #define PRINT_REG(text,reg) REAL_PRINT_REG(text,reg)
 #else
 
@@ -4796,7 +4796,6 @@ stmt: ARG_OBJ (reg) {
        int sa;
        
        mono_assert (size > 0);
-
        sa = size + 3;
        sa &= ~3;
 
index 87459299314caf1aa4df26a07bdf889281191f85..8fbc5c8230a2cb6304bbe115d2b2bc5b67c0a7a2 100644 (file)
@@ -1,3 +1,7 @@
+2002-07-16  Dietmar Maurer  <dietmar@ximian.com>
+
+       * marshal.c (mono_marshal_get_native_wrapper): support valuetypes
+
 2002-07-15  Dietmar Maurer  <dietmar@ximian.com>
 
        * marshal.c (mono_marshal_get_native_wrapper): handle enum types
index a2dc8bf43a3695e90b212d8369c1c61ebaeb8848..c77ae04cc53db6aa45387b84c31f159dae2de04c 100644 (file)
@@ -97,8 +97,8 @@ mono_array_to_lparray (MonoArray *array)
        if (!array)
                return NULL;
 
-       g_assert_not_reached ();
-       return NULL;
+       /* fixme: maybe we need to make a copy */
+       return array->vector;
 }
 
 gpointer
@@ -450,22 +450,22 @@ emit_str_to_ptr_conv (MonoMethodBuilder *mb, MonoMarshalConv conv, int usize, in
        case MONO_MARSHAL_CONV_STR_TBSTR:
        case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
        case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
-               /* free space if ARG_2 == true */
-               mono_mb_emit_byte (mb, CEE_LDARG_2);
+               /* free space if free == true */
+               mono_mb_emit_byte (mb, CEE_LDLOC_2);
                mono_mb_emit_byte (mb, CEE_BRFALSE_S);
                mono_mb_emit_byte (mb, 4);
                mono_mb_emit_byte (mb, CEE_LDLOC_1);
                mono_mb_emit_byte (mb, CEE_LDIND_I);
                mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
                mono_mb_emit_byte (mb, CEE_MONO_FREE);
-               
+
                mono_mb_emit_byte (mb, CEE_LDLOC_1);
                mono_mb_emit_byte (mb, CEE_LDLOC_0);
                mono_mb_emit_byte (mb, CEE_LDIND_I);
                mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
                mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
                mono_mb_emit_byte (mb, conv);
-               mono_mb_emit_byte (mb, CEE_STIND_I);
+               mono_mb_emit_byte (mb, CEE_STIND_I);    
                break;
        case MONO_MARSHAL_CONV_STR_BYVALSTR: 
        case MONO_MARSHAL_CONV_STR_BYVALWSTR: {
@@ -1434,6 +1434,7 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoObject *this)
 {
        MonoMethodSignature *sig, *csig;
        MonoMethodBuilder *mb;
+       MonoClass *klass;
        MonoMethod *res;
        GHashTable *cache;
        int i, sigsize;
@@ -1471,7 +1472,12 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoObject *this)
 
        for (i = 0; i < sig->param_count; i++) {
                MonoType *t = sig->params [i];
-               
+
+               if (t->byref) {
+                       /* fixme: */
+                       g_assert_not_reached ();
+               }
+
                switch (t->type) {
                case MONO_TYPE_I1:
                case MONO_TYPE_U1:
@@ -1502,6 +1508,15 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoObject *this)
                        /* fixme: conversions ? */
                        mono_mb_emit_ldarg (mb, i);
                        break;
+               case MONO_TYPE_VALUETYPE:
+                       klass = sig->params [i]->data.klass;
+                       if (klass->enumtype) {
+                               mono_mb_emit_ldarg (mb, i);
+                               break;
+                       }
+
+                       g_assert_not_reached ();
+                       break;
                default:
                        g_warning ("type 0x%02x unknown", t->type);     
                        g_assert_not_reached ();
@@ -1524,7 +1539,7 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoObject *this)
 
 /*
  * generates IL code for the pinvoke wrapper (the generated method
- * call the unamnage code in method->addr)
+ * calls the unamnage code in method->addr)
  */
 MonoMethod *
 mono_marshal_get_native_wrapper (MonoMethod *method)
@@ -1570,8 +1585,10 @@ mono_marshal_get_native_wrapper (MonoMethod *method)
        sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
        csig = g_memdup (sig, sigsize);
 
+       /* internal calls: we simply push all arguments and call the method (no conversions) */
        if (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
 
+               /* hack - string constructors returns a value */
                if (method->string_ctor)
                        csig->ret = &mono_defaults.string_class->byval_arg;
 
@@ -1594,13 +1611,20 @@ mono_marshal_get_native_wrapper (MonoMethod *method)
 
        g_assert (pinvoke);
 
+       /* pinvoke: we need to convert the arguments if necessary */
+
+       csig->pinvoke = 1;
+
        /* we allocate local for use with emit_struct_conv() */
        /* allocate local 0 (pointer) src_ptr */
        mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
        /* allocate local 1 (pointer) dst_ptr */
        mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
-       /* allocate local 2 (pointer) as tmp/scratch storage */
-       mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
+       /* allocate local 2 (boolean) delete_old */
+       mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
+
+       mono_mb_emit_icon (mb, 0);
+       mono_mb_emit_byte (mb, CEE_STLOC_2);
 
        if (sig->ret->type != MONO_TYPE_VOID) {
                /* allocate local 3 to store the return value */
@@ -1613,35 +1637,38 @@ mono_marshal_get_native_wrapper (MonoMethod *method)
                MonoType *t = sig->params [i];
 
                argnum = i + sig->hasthis;
-
-               /* allocate one tmp/scratch storage for each parameter */
-               tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
+               tmp_locals [i] = 0;
 
                switch (t->type) {
                case MONO_TYPE_VALUETYPE:
+                       
                        klass = sig->params [i]->data.klass;
                        if (klass->enumtype)
                                break;
+
+                       tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
                        
                        /* store the address of the source into local variable 0 */
-                       mono_mb_emit_byte (mb, CEE_LDARGA);
-                       mono_mb_emit_i2 (mb, argnum);
+                       mono_mb_emit_ldarg_addr (mb, argnum);
                        mono_mb_emit_byte (mb, CEE_STLOC_0);
                        
                        /* allocate space for the native struct and
                         * store the address into local variable 1 (dest) */
                        mono_mb_emit_icon (mb, mono_class_native_size (klass));
+                       mono_mb_emit_byte (mb, CEE_PREFIX1);
                        mono_mb_emit_byte (mb, CEE_LOCALLOC);
                        mono_mb_emit_stloc (mb, tmp_locals [i]);
+                       /* set dst_ptr */
                        mono_mb_emit_ldloc (mb, tmp_locals [i]);
                        mono_mb_emit_byte (mb, CEE_STLOC_1);
 
                        /* emit valuetype convnversion code code */
                        emit_struct_conv (mb, sig->params [i]->data.klass, FALSE);
-
                        break;
                case MONO_TYPE_STRING:
-                       /* fixme: load the address instead */
+                       csig->params [argnum] = &mono_defaults.int_class->byval_arg;
+                       tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
+
                        mono_mb_emit_ldarg (mb, argnum);
                        mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
                        mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
@@ -1650,6 +1677,9 @@ mono_marshal_get_native_wrapper (MonoMethod *method)
                        break;
                case MONO_TYPE_CLASS:
                case MONO_TYPE_OBJECT:
+                       csig->params [argnum] = &mono_defaults.int_class->byval_arg;
+                       tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
+
                        if (t->data.klass->delegate) {
                                mono_mb_emit_ldarg (mb, argnum);
                                mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
@@ -1664,6 +1694,17 @@ mono_marshal_get_native_wrapper (MonoMethod *method)
                                mono_mb_emit_stloc (mb, tmp_locals [i]);
                        }
                        break;
+               case MONO_TYPE_ARRAY:
+               case MONO_TYPE_SZARRAY:
+                       csig->params [argnum] = &mono_defaults.int_class->byval_arg;
+                       tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
+
+                       mono_mb_emit_ldarg (mb, argnum);
+                       mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+                       mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
+                       mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_ARRAY_LPARRAY);
+                       mono_mb_emit_stloc (mb, tmp_locals [i]);
+                       break;
                }
        }
 
@@ -1678,6 +1719,7 @@ mono_marshal_get_native_wrapper (MonoMethod *method)
                argnum = i + sig->hasthis;
 
                if (t->byref) {
+                       g_assert_not_reached ();
                        mono_mb_emit_ldarg (mb, argnum);
                        continue;
                }
@@ -1707,23 +1749,32 @@ mono_marshal_get_native_wrapper (MonoMethod *method)
                                mono_mb_emit_ldarg (mb, argnum);
                                break;
                        }                       
+                       g_assert (tmp_locals [i]);
                        mono_mb_emit_ldloc (mb, tmp_locals [i]);
-                       //mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
-                       //mono_mb_emit_byte (mb, CEE_MONO_LDOBJ);
-                       //mono_mb_emit_i4 (mb, mono_klass_native_size (klass));
-
+                       mono_mb_emit_byte (mb, CEE_LDOBJ);
+                       mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
                        break;
                case MONO_TYPE_STRING:
                        /* fixme: load the address instead */
+                       g_assert (tmp_locals [i]);
                        mono_mb_emit_ldloc (mb, tmp_locals [i]);
                        break;
                case MONO_TYPE_CLASS:
                case MONO_TYPE_OBJECT:
+                       g_assert (tmp_locals [i]);
                        mono_mb_emit_ldloc (mb, tmp_locals [i]);
                        break;
                case MONO_TYPE_CHAR:
+                       /* fixme: dont know how to marshal that. We cant simply
+                        * convert it to a one byte UTF8 character, because an
+                        * unicode character may need more that one byte in UTF8 */
+                       mono_mb_emit_ldarg (mb, argnum);
+                       break;
                case MONO_TYPE_ARRAY:
                case MONO_TYPE_SZARRAY:
+                       g_assert (tmp_locals [i]);
+                       mono_mb_emit_ldloc (mb, tmp_locals [i]);
+                       break;
                case MONO_TYPE_TYPEDBYREF:
                case MONO_TYPE_FNPTR:
                default:
@@ -1735,6 +1786,8 @@ mono_marshal_get_native_wrapper (MonoMethod *method)
        /* call the native method */
        mono_mb_emit_native_call (mb, csig, method->addr);
 
+       /* return the result */
+
        type = sig->ret->type;
 handle_enum:
        switch (type) {
@@ -1778,6 +1831,8 @@ handle_enum:
                /* fixme: we need conversions here */
                break;
        case MONO_TYPE_CHAR:
+               /* fixme: we need conversions here */
+               break;
        case MONO_TYPE_TYPEDBYREF:
        case MONO_TYPE_FNPTR:
        default:
@@ -1820,8 +1875,10 @@ mono_marshal_get_struct_to_ptr (MonoClass *klass)
        mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
        /* allocate local 1 (pointer) dst_ptr */
        mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
-       /* allocate local 2 (pointer) as tmp/scratch storage */
-       mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
+       /* allocate local 2 (boolean) delete_old */
+       mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
+       mono_mb_emit_byte (mb, CEE_LDARG_2);
+       mono_mb_emit_byte (mb, CEE_STLOC_2);
 
        /* initialize src_ptr to point to the start of object data */
        mono_mb_emit_byte (mb, CEE_LDARG_0);
@@ -1869,8 +1926,10 @@ mono_marshal_get_ptr_to_struct (MonoClass *klass)
        mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
        /* allocate local 1 (pointer) dst_ptr */
        mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
-       /* allocate local 2 (pointer) as tmp/scratch storage */
-       mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
+       /* allocate local 2 (boolean) delete_old */
+       mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
+       mono_mb_emit_byte (mb, CEE_LDARG_2);
+       mono_mb_emit_byte (mb, CEE_STLOC_2);
 
        /* initialize src_ptr to point to the start of object data */
        mono_mb_emit_byte (mb, CEE_LDARG_0);
index d98e27abbd5bbc5eb0ed401d4ac7458fddc8321f..ff81fe406abc2239402716c5d2fd91d6a004d556 100644 (file)
@@ -268,7 +268,8 @@ struct _MonoMethodSignature {
        unsigned int  hasthis : 1;
        unsigned int  explicit_this   : 1;
        unsigned int  call_convention : 6;
-       unsigned int  ref_count : 24;
+       unsigned int  pinvoke   : 1;
+       unsigned int  ref_count : 23;
        guint16       param_count;
        guint16       sentinelpos;
        MonoType     *ret;
index 24d440fe29d59d0a89992d670503cda010886dcd..2acf38409839bcad8c994cd02a76c0361a3cf3f0 100644 (file)
@@ -41,6 +41,8 @@ TESTSRC=                      \
        static-constructor.cs   \
        pinvoke.cs              \
        pinvoke1.cs             \
+       pinvoke2.cs             \
+       pinvoke3.cs             \
        box.cs                  \
        array.cs                \
        enum.cs                 \
index 081e360adba68ba43857452d868b83244e6dbd5d..2bc89f1069df0d6a6b2f73ddf457f9a1fe14a0c5 100644 (file)
@@ -32,10 +32,10 @@ mono_test_puts_static (char *s)
        return 1;
 }
 
-typedef int (*SimpleDelegate) (int a, int b);
+typedef int (*SimpleDelegate3) (int a, int b);
 
 int
-mono_invoke_delegate (SimpleDelegate delegate)
+mono_invoke_delegate (SimpleDelegate3 delegate)
 {
        int res;
 
@@ -47,3 +47,65 @@ mono_invoke_delegate (SimpleDelegate delegate)
 
        return res;
 }
+
+int 
+mono_test_marshal_char (short a1)
+{
+       if (a1 = 'a')
+               return 0;
+       
+       return 1;
+}
+
+int 
+mono_test_marshal_array (int *a1)
+{
+       int i, sum = 0;
+
+       for (i = 0; i < 50; i++)
+               sum += a1 [i];
+       
+       return sum;
+}
+
+typedef struct {
+       int a;
+       int b;
+       int c;
+       char *d;
+} simplestruct;
+
+int 
+mono_test_marshal_struct (simplestruct ss)
+{
+       if (ss.a == 0 && ss.b == 1 && ss.c == 0 &&
+           !strcmp (ss.d, "TEST"))
+               return 0;
+
+       return 1;
+}
+
+
+typedef int (*SimpleDelegate) (int a);
+
+int
+mono_test_marshal_delegate (SimpleDelegate delegate)
+{
+       return delegate (2);
+}
+
+typedef int (*SimpleDelegate2) (simplestruct ss);
+
+int
+mono_test_marshal_delegate2 (SimpleDelegate2 delegate)
+{
+       simplestruct ss;
+
+       ss.a = 0;
+       ss.b = 1;
+       ss.c = 0;
+       ss.d = "TEST";
+
+       return delegate (ss);
+}
+
index e3697293565133b45f5fcc1cea717bd4b9521ff2..bb19ef2e5a1b2f9402fef980d1103f020d717cfc 100755 (executable)
@@ -23,6 +23,7 @@ public class Test {
        
        public unsafe static int Main () {
                SimpleStruct ss = new SimpleStruct ();
+               SimpleStruct cp = new SimpleStruct ();
                int size = Marshal.SizeOf (typeof (SimpleStruct));
                
                Console.WriteLine ("SimpleStruct:" + size);
@@ -67,6 +68,10 @@ public class Test {
                        return 1;
                if (Marshal.ReadInt32 (p, 28) != 4)
                        return 1;
+
+               object o = cp;
+               Marshal.PtrToStructure (p, o);
+               cp = (SimpleStruct)o;
                
                return 0;
        }
diff --git a/mono/tests/pinvoke2.cs b/mono/tests/pinvoke2.cs
new file mode 100755 (executable)
index 0000000..a65d234
--- /dev/null
@@ -0,0 +1,61 @@
+using System;
+using System.Runtime.InteropServices;
+
+public class Test {
+
+       public static int delegate_test (int a)
+       {
+               Console.WriteLine ("Delegate: " + a);
+               
+               if (a == 2)
+                       return 0;
+
+               return 1;
+       }
+       
+       [StructLayout (LayoutKind.Sequential)]
+       public struct SimpleStruct {
+               public bool a;
+               public bool b;
+               public bool c;
+               public string d;
+       }
+
+       [DllImport ("libtest.so", EntryPoint="mono_test_marshal_char")]
+       public static extern int mono_test_marshal_char (char a1);
+
+       [DllImport ("libtest.so", EntryPoint="mono_test_marshal_array")]
+       public static extern int mono_test_marshal_array (int [] a1);
+       
+       [DllImport ("libtest.so", EntryPoint="mono_test_marshal_struct")]
+       public static extern int mono_test_marshal_struct (SimpleStruct ss);
+
+       [DllImport ("libtest.so", EntryPoint="mono_test_marshal_delegate")]
+       public static extern int mono_test_marshal_delegate (SimpleDelegate d);
+
+       public delegate int SimpleDelegate (int a);
+
+       public static int Main () {
+               if (mono_test_marshal_char ('a') != 0)
+                       return 1;
+
+               int [] a1 = new int [50];
+               for (int i = 0; i < 50; i++)
+                       a1 [i] = i;
+
+               if (mono_test_marshal_array (a1) != 1225)
+                       return 2;
+
+               SimpleStruct ss = new  SimpleStruct ();
+               ss.b = true;
+               ss.d = "TEST";
+               mono_test_marshal_struct (ss);
+               
+               SimpleDelegate d = new SimpleDelegate (delegate_test);
+
+               if (mono_test_marshal_delegate (d) != 0)
+                       return 1;
+               
+               return 0;
+       }
+}
diff --git a/mono/tests/pinvoke3.cs b/mono/tests/pinvoke3.cs
new file mode 100755 (executable)
index 0000000..fe1914a
--- /dev/null
@@ -0,0 +1,38 @@
+using System;
+using System.Runtime.InteropServices;
+
+public class Test {
+
+       [StructLayout (LayoutKind.Sequential)]
+       public struct SimpleStruct {
+               public bool a;
+               public bool b;
+               public bool c;
+               public string d;
+       }
+
+       public static int delegate_test (SimpleStruct ss)
+       {
+               Console.WriteLine ("Delegate: " + ss);
+               
+               if (!ss.a && ss.b && !ss.c && ss.d == "TEST")
+                       return 0;
+               
+               return 1;
+       }
+       
+       [DllImport ("libtest.so", EntryPoint="mono_test_marshal_delegate2")]
+       public static extern int mono_test_marshal_delegate2 (SimpleDelegate2 d);
+
+       public delegate int SimpleDelegate2 (SimpleStruct ss);
+
+       public static int Main () {
+               
+               SimpleDelegate2 d = new SimpleDelegate2 (delegate_test);
+
+               if (mono_test_marshal_delegate2 (d) != 0)
+                       return 1;
+               
+               return 0;
+       }
+}