2 * marshal.c: Routines for marshaling complex types in P/Invoke methods.
5 * Paolo Molaro (lupus@ximian.com)
7 * (C) 2002 Ximian, Inc. http://www.ximian.com
14 #include "metadata/marshal.h"
15 #include "metadata/tabledefs.h"
16 #include "metadata/exception.h"
17 #include "metadata/appdomain.h"
18 #include "mono/metadata/debug-helpers.h"
20 //#define DEBUG_RUNTIME_CODE
22 #define OPDEF(a,b,c,d,e,f,g,h,i,j) \
26 #include "mono/cil/opcode.def"
31 struct _MonoMethodBuilder {
35 guint32 code_size, pos;
40 indenter (MonoDisHelper *dh, MonoMethod *method, guint32 ip_offset)
42 return g_strdup (" ");
45 static MonoDisHelper marshal_dh = {
55 mono_delegate_to_ftnptr (MonoDelegate *delegate)
57 MonoMethod *method, *invoke, *wrapper;
58 MonoMethodSignature *sig;
64 if (delegate->delegate_trampoline)
65 return delegate->delegate_trampoline;
67 klass = ((MonoObject *)delegate)->vtable->klass;
68 g_assert (klass->delegate);
70 method = delegate->method_info->method;
71 sig = method->signature;
73 invoke = mono_get_delegate_invoke (klass);
74 wrapper = mono_marshal_get_managed_wrapper (invoke, (MonoObject *)delegate);
76 delegate->delegate_trampoline = mono_compile_method (wrapper);
78 return delegate->delegate_trampoline;
82 mono_array_to_savearray (MonoArray *array)
87 g_assert_not_reached ();
92 mono_array_to_lparray (MonoArray *array)
97 g_assert_not_reached ();
102 mono_string_to_ansibstr (MonoString *string_obj)
104 g_error ("implement me");
109 mono_string_to_bstr (MonoString *string_obj)
111 g_error ("implement me");
116 mono_string_to_byvalstr (gpointer dst, MonoString *src, int size)
121 g_assert (dst != NULL);
125 memset (dst, 0, size);
129 s = mono_string_to_utf8 (src);
130 len = MIN (size, strlen (s));
131 memcpy (dst, s, len);
134 *((char *)dst + size - 1) = 0;
138 mono_string_to_byvalwstr (gpointer dst, MonoString *src, int size)
142 g_assert (dst != NULL);
146 memset (dst, 0, size);
150 len = MIN (size, (mono_string_length (src) * 2));
151 memcpy (dst, mono_string_chars (src), len);
153 *((char *)dst + size - 1) = 0;
154 *((char *)dst + size - 2) = 0;
159 mono_find_method_by_name (MonoClass *klass, const char *name, int param_count)
161 MonoMethod *res = NULL;
164 for (i = 0; i < klass->method.count; ++i) {
165 if ((klass->methods [i]->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
166 klass->methods [i]->name[0] == name [0] &&
167 !strcmp (name, klass->methods [i]->name) &&
168 klass->methods [i]->signature->param_count == param_count) {
169 res = klass->methods [i];
177 mono_mb_free (MonoMethodBuilder *mb)
179 g_list_free (mb->locals_list);
184 mono_mb_new (MonoClass *klass, const char *name)
186 MonoMethodBuilder *mb;
189 g_assert (klass != NULL);
190 g_assert (name != NULL);
192 mb = g_new0 (MonoMethodBuilder, 1);
194 mb->method = m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
197 m->name = g_strdup (name);
199 m->inline_count = -1;
200 m->wrapper_type = MONO_WRAPPER_UNKNOWN;
203 mb->code = g_malloc (mb->code_size);
209 mono_mb_add_local (MonoMethodBuilder *mb, MonoType *type)
211 int res = mb->locals;
213 g_assert (mb != NULL);
214 g_assert (type != NULL);
216 mb->locals_list = g_list_append (mb->locals_list, type);
223 mono_mb_create_method (MonoMethodBuilder *mb, MonoMethodSignature *signature, int max_stack)
225 MonoMethodHeader *header;
229 g_assert (mb != NULL);
231 ((MonoMethodNormal *)mb->method)->header = header = (MonoMethodHeader *)
232 g_malloc0 (sizeof (MonoMethodHeader) + mb->locals * sizeof (MonoType *));
237 header->max_stack = max_stack;
239 for (i = 0, l = mb->locals_list; l; l = l->next, i++) {
240 header->locals [i] = (MonoType *)l->data;
243 mb->method->signature = signature;
244 header->code = mb->code;
245 header->code_size = mb->pos;
246 header->num_locals = mb->locals;
248 #ifdef DEBUG_RUNTIME_CODE
249 printf ("RUNTIME CODE FOR %s\n", mono_method_full_name (mb->method, TRUE));
250 printf ("%s\n", mono_disasm_code (&marshal_dh, mb->method, mb->code, mb->code + mb->pos));
257 mono_mb_add_data (MonoMethodBuilder *mb, gpointer data)
259 MonoMethodWrapper *mw;
261 g_assert (mb != NULL);
263 mw = (MonoMethodWrapper *)mb->method;
265 mw->data = g_list_append (mw->data, data);
267 return g_list_length (mw->data);
271 mono_mb_patch_addr (MonoMethodBuilder *mb, int pos, int value)
273 *((gint32 *)(&mb->code [pos])) = value;
277 mono_mb_emit_byte (MonoMethodBuilder *mb, guint8 op)
279 if (mb->pos >= mb->code_size) {
281 mb->code = g_realloc (mb->code, mb->code_size);
284 mb->code [mb->pos++] = op;
288 mono_mb_emit_i4 (MonoMethodBuilder *mb, gint32 data)
290 if ((mb->pos + 4) >= mb->code_size) {
292 mb->code = g_realloc (mb->code, mb->code_size);
295 *((gint32 *)(&mb->code [mb->pos])) = data;
300 mono_mb_emit_i2 (MonoMethodBuilder *mb, gint16 data)
302 if ((mb->pos + 2) >= mb->code_size) {
304 mb->code = g_realloc (mb->code, mb->code_size);
307 *((gint16 *)(&mb->code [mb->pos])) = data;
312 mono_mb_emit_ldarg (MonoMethodBuilder *mb, guint argnum)
315 mono_mb_emit_byte (mb, CEE_LDARG_0 + argnum);
316 } else if (argnum < 256) {
317 mono_mb_emit_byte (mb, CEE_LDARG_S);
318 mono_mb_emit_byte (mb, argnum);
320 mono_mb_emit_byte (mb, CEE_PREFIX1);
321 mono_mb_emit_byte (mb, CEE_LDARG);
322 mono_mb_emit_i4 (mb, argnum);
327 mono_mb_emit_ldarg_addr (MonoMethodBuilder *mb, guint argnum)
330 mono_mb_emit_byte (mb, CEE_LDARGA_S);
331 mono_mb_emit_byte (mb, argnum);
333 mono_mb_emit_byte (mb, CEE_PREFIX1);
334 mono_mb_emit_byte (mb, CEE_LDARGA);
335 mono_mb_emit_i4 (mb, argnum);
340 mono_mb_emit_ldloc (MonoMethodBuilder *mb, guint num)
343 mono_mb_emit_byte (mb, CEE_LDLOC_0 + num);
344 } else if (num < 256) {
345 mono_mb_emit_byte (mb, CEE_LDLOC_S);
346 mono_mb_emit_byte (mb, num);
348 mono_mb_emit_byte (mb, CEE_PREFIX1);
349 mono_mb_emit_byte (mb, CEE_LDLOC);
350 mono_mb_emit_i4 (mb, num);
355 mono_mb_emit_stloc (MonoMethodBuilder *mb, guint num)
358 mono_mb_emit_byte (mb, CEE_STLOC_0 + num);
359 } else if (num < 256) {
360 mono_mb_emit_byte (mb, CEE_STLOC_S);
361 mono_mb_emit_byte (mb, num);
363 mono_mb_emit_byte (mb, CEE_PREFIX1);
364 mono_mb_emit_byte (mb, CEE_STLOC);
365 mono_mb_emit_i4 (mb, num);
370 mono_mb_emit_icon (MonoMethodBuilder *mb, gint32 value)
372 if (value >= -1 && value < 8) {
373 mono_mb_emit_byte (mb, CEE_LDC_I4_0 + value);
374 } else if (value >= -128 && value <= 127) {
375 mono_mb_emit_byte (mb, CEE_LDC_I4_S);
376 mono_mb_emit_byte (mb, value);
378 mono_mb_emit_byte (mb, CEE_LDC_I4);
379 mono_mb_emit_i4 (mb, value);
384 mono_mb_emit_managed_call (MonoMethodBuilder *mb, MonoMethod *method, MonoMethodSignature *opt_sig)
387 opt_sig = method->signature;
388 mono_mb_emit_byte (mb, CEE_PREFIX1);
389 mono_mb_emit_byte (mb, CEE_LDFTN);
390 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, method));
391 mono_mb_emit_byte (mb, CEE_CALLI);
392 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, opt_sig));
396 mono_mb_emit_native_call (MonoMethodBuilder *mb, MonoMethodSignature *sig, gpointer func)
398 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
399 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
400 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, func));
401 mono_mb_emit_byte (mb, CEE_CALLI);
402 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, sig));
406 mono_mb_emit_exception (MonoMethodBuilder *mb)
408 mono_mb_emit_byte (mb, CEE_LDNULL);
409 mono_mb_emit_byte (mb, CEE_THROW);
414 mono_mb_emit_add_to_local (MonoMethodBuilder *mb, guint8 local, gint8 incr)
416 mono_mb_emit_ldloc (mb, local);
417 mono_mb_emit_icon (mb, incr);
418 mono_mb_emit_byte (mb, CEE_ADD);
419 mono_mb_emit_stloc (mb, local);
423 emit_ptr_to_str_conv (MonoMethodBuilder *mb, MonoMarshalConv conv, int usize, int msize)
425 /* fixme: dont know what do do here - docs say
426 this does not work for value types */
428 g_warning ("not implemented");
429 g_assert_not_reached ();
433 emit_str_to_ptr_conv (MonoMethodBuilder *mb, MonoMarshalConv conv, int usize, int msize)
436 case MONO_MARSHAL_CONV_BOOL_I4:
437 mono_mb_emit_byte (mb, CEE_LDLOC_1);
438 mono_mb_emit_byte (mb, CEE_LDLOC_0);
439 mono_mb_emit_byte (mb, CEE_LDIND_U1);
440 mono_mb_emit_byte (mb, CEE_STIND_I4);
442 case MONO_MARSHAL_CONV_STR_LPWSTR:
443 case MONO_MARSHAL_CONV_STR_LPSTR:
444 case MONO_MARSHAL_CONV_STR_LPTSTR:
445 case MONO_MARSHAL_CONV_STR_BSTR:
446 case MONO_MARSHAL_CONV_STR_ANSIBSTR:
447 case MONO_MARSHAL_CONV_STR_TBSTR:
448 case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
449 case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
450 /* free space if ARG_2 == true */
451 mono_mb_emit_byte (mb, CEE_LDARG_2);
452 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
453 mono_mb_emit_byte (mb, 4);
454 mono_mb_emit_byte (mb, CEE_LDLOC_1);
455 mono_mb_emit_byte (mb, CEE_LDIND_I);
456 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
457 mono_mb_emit_byte (mb, CEE_MONO_FREE);
459 mono_mb_emit_byte (mb, CEE_LDLOC_1);
460 mono_mb_emit_byte (mb, CEE_LDLOC_0);
461 mono_mb_emit_byte (mb, CEE_LDIND_I);
462 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
463 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
464 mono_mb_emit_byte (mb, conv);
465 mono_mb_emit_byte (mb, CEE_STIND_I);
467 case MONO_MARSHAL_CONV_STR_BYVALSTR:
468 case MONO_MARSHAL_CONV_STR_BYVALWSTR: {
472 mono_mb_emit_byte (mb, CEE_LDLOC_1); /* dst */
473 mono_mb_emit_byte (mb, CEE_LDLOC_0);
474 mono_mb_emit_byte (mb, CEE_LDIND_I); /* src String */
475 mono_mb_emit_icon (mb, usize);
476 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
477 mono_mb_emit_byte (mb, CEE_MONO_PROC3);
478 mono_mb_emit_byte (mb, conv);
481 case MONO_MARSHAL_CONV_ARRAY_BYVALARRAY: {
485 mono_mb_emit_byte (mb, CEE_LDLOC_0);
486 mono_mb_emit_byte (mb, CEE_LDIND_I);
487 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
488 mono_mb_emit_byte (mb, 15);
490 mono_mb_emit_byte (mb, CEE_LDLOC_1);
491 mono_mb_emit_byte (mb, CEE_LDLOC_0);
492 mono_mb_emit_byte (mb, CEE_LDIND_I);
493 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
494 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
495 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoArray, vector));
496 mono_mb_emit_byte (mb, CEE_ADD);
497 mono_mb_emit_icon (mb, usize);
498 mono_mb_emit_byte (mb, CEE_PREFIX1);
499 mono_mb_emit_byte (mb, CEE_CPBLK);
502 case MONO_MARSHAL_CONV_BOOL_VARIANTBOOL:
504 g_error ("marshalling conversion %d not implemented", conv);
509 emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object)
511 MonoMarshalType *info;
514 info = mono_marshal_load_type_info (klass);
516 for (i = 0; i < info->num_fields; i++) {
517 MonoMarshalNative ntype;
518 MonoMarshalConv conv;
519 MonoType *ftype = info->fields [i].field->type;
522 gboolean last_field = i < (info->num_fields -1) ? 0 : 1;
524 if (ftype->attrs & FIELD_ATTRIBUTE_STATIC)
527 ntype = mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE, klass->unicode, &conv);
530 msize = klass->instance_size - info->fields [i].field->offset;
531 usize = info->native_size - info->fields [i].offset;
533 msize = klass->fields [i + 1].offset - info->fields [i].field->offset;
534 usize = info->fields [i + 1].offset - info->fields [i].offset;
536 g_assert (msize > 0 && usize > 0);
539 case MONO_MARSHAL_CONV_NONE:
541 if (ftype->byref || ftype->type == MONO_TYPE_I ||
542 ftype->type == MONO_TYPE_U) {
543 mono_mb_emit_byte (mb, CEE_LDLOC_1);
544 mono_mb_emit_byte (mb, CEE_LDLOC_0);
545 mono_mb_emit_byte (mb, CEE_LDIND_I);
546 mono_mb_emit_byte (mb, CEE_STIND_I);
550 switch (ftype->type) {
553 mono_mb_emit_byte (mb, CEE_LDLOC_1);
554 mono_mb_emit_byte (mb, CEE_LDLOC_0);
555 mono_mb_emit_byte (mb, CEE_LDIND_I4);
556 mono_mb_emit_byte (mb, CEE_STIND_I4);
560 case MONO_TYPE_BOOLEAN:
561 mono_mb_emit_byte (mb, CEE_LDLOC_1);
562 mono_mb_emit_byte (mb, CEE_LDLOC_0);
563 mono_mb_emit_byte (mb, CEE_LDIND_I1);
564 mono_mb_emit_byte (mb, CEE_STIND_I1);
568 mono_mb_emit_byte (mb, CEE_LDLOC_1);
569 mono_mb_emit_byte (mb, CEE_LDLOC_0);
570 mono_mb_emit_byte (mb, CEE_LDIND_I2);
571 mono_mb_emit_byte (mb, CEE_STIND_I2);
575 mono_mb_emit_byte (mb, CEE_LDLOC_1);
576 mono_mb_emit_byte (mb, CEE_LDLOC_0);
577 mono_mb_emit_byte (mb, CEE_LDIND_I8);
578 mono_mb_emit_byte (mb, CEE_STIND_I8);
581 mono_mb_emit_byte (mb, CEE_LDLOC_1);
582 mono_mb_emit_byte (mb, CEE_LDLOC_0);
583 mono_mb_emit_byte (mb, CEE_LDIND_R4);
584 mono_mb_emit_byte (mb, CEE_STIND_R4);
587 mono_mb_emit_byte (mb, CEE_LDLOC_1);
588 mono_mb_emit_byte (mb, CEE_LDLOC_0);
589 mono_mb_emit_byte (mb, CEE_LDIND_R8);
590 mono_mb_emit_byte (mb, CEE_STIND_R8);
592 case MONO_TYPE_VALUETYPE:
593 emit_struct_conv (mb, ftype->data.klass, to_object);
596 g_error ("marshalling type %02x not implemented", ftype->type);
602 emit_ptr_to_str_conv (mb, conv, usize, msize);
604 emit_str_to_ptr_conv (mb, conv, usize, msize);
608 mono_mb_emit_add_to_local (mb, 0, msize);
609 mono_mb_emit_add_to_local (mb, 1, usize);
615 delegate_test (MonoDelegate *delegate, gpointer *params)
617 g_assert_not_reached ();
622 mono_marshal_get_delegate_begin_invoke (MonoMethod *method)
624 MonoMethodSignature *sig;
625 static MonoMethodSignature *csig = NULL;
626 MonoMethodBuilder *mb;
632 g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
633 !strcmp (method->name, "BeginInvoke"));
635 sig = method->signature;
637 cache = method->klass->image->delegate_begin_invoke_cache;
638 if ((res = (MonoMethod *)g_hash_table_lookup (cache, sig)))
642 ret_type = &mono_defaults.int_class->byval_arg;
643 else if (sig->ret->type == MONO_TYPE_VALUETYPE && sig->ret->data.klass->enumtype)
644 ret_type = sig->ret->data.klass->enum_basetype;
649 int sigsize = sizeof (MonoMethodSignature) + 2 * sizeof (MonoType *);
650 csig = g_malloc0 (sigsize);
652 /* MonoObject *begin_invoke (MonoDelegate *delegate, gpointer params[]) */
653 csig->param_count = 2;
654 csig->ret = &mono_defaults.object_class->byval_arg;
655 csig->params [0] = &mono_defaults.object_class->byval_arg;
656 csig->params [1] = &mono_defaults.int_class->byval_arg;
659 mb = mono_mb_new (method->klass, method->name);
660 mb->method->wrapper_type = MONO_WRAPPER_DELEGATE_BEGIN_INVOKE;
662 /* allocate local 0 (pointer) *params[] */
663 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
664 /* allocate local 1 (pointer) tmo */
665 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
667 /* alloate space on stack to store an array of pointers to the arguments */
668 mono_mb_emit_icon (mb, sizeof (gpointer) * (sig->param_count + 1));
669 mono_mb_emit_byte (mb, CEE_PREFIX1);
670 mono_mb_emit_byte (mb, CEE_LOCALLOC);
671 mono_mb_emit_byte (mb, CEE_STLOC_0);
674 mono_mb_emit_byte (mb, CEE_LDLOC_0);
675 mono_mb_emit_byte (mb, CEE_STLOC_1);
677 for (i = 0; i < sig->param_count; i++) {
679 mono_mb_emit_byte (mb, CEE_LDLOC_1);
680 mono_mb_emit_ldarg_addr (mb, i);
681 mono_mb_emit_byte (mb, CEE_STIND_I);
682 /* tmp = tmp + sizeof (gpointer) */
683 if (i < (sig->param_count - 1))
684 mono_mb_emit_add_to_local (mb, 1, sizeof (gpointer));
687 mono_mb_emit_ldarg (mb, 0);
688 mono_mb_emit_byte (mb, CEE_LDLOC_0);
689 mono_mb_emit_native_call (mb, csig, delegate_test);
691 /* unbox the result if necessary */
693 switch (ret_type->type) {
694 case MONO_TYPE_STRING:
695 case MONO_TYPE_CLASS:
696 case MONO_TYPE_OBJECT:
697 case MONO_TYPE_ARRAY:
698 case MONO_TYPE_SZARRAY:
704 case MONO_TYPE_BOOLEAN:
716 case MONO_TYPE_VALUETYPE:
717 mono_mb_emit_byte (mb, CEE_UNBOX);
718 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (ret_type)));
721 g_warning ("type 0x%x not handled", ret_type->type);
722 g_assert_not_reached ();
725 mono_mb_emit_byte (mb, CEE_RET);
727 res = mono_mb_create_method (mb, sig, 0);
729 g_hash_table_insert (cache, sig, res);
734 * the returned method invokes all methods in a multicast delegate
737 mono_marshal_get_delegate_invoke (MonoMethod *method)
739 MonoMethodSignature *sig, *static_sig;
741 MonoMethodBuilder *mb;
746 g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
747 !strcmp (method->name, "Invoke"));
749 sig = method->signature;
751 cache = method->klass->image->delegate_invoke_cache;
752 if ((res = (MonoMethod *)g_hash_table_lookup (cache, sig)))
755 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
756 static_sig = g_memdup (sig, sigsize);
757 static_sig->hasthis = 0;
759 mb = mono_mb_new (method->klass, method->name);
760 mb->method->wrapper_type = MONO_WRAPPER_DELEGATE_INVOKE;
762 /* allocate local 0 (object) prev */
763 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
764 /* allocate local 1 (object) target */
765 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
766 /* allocate local 2 (pointer) mptr */
767 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
769 /* allocate local 3 to store the return value */
770 if (sig->ret->type != MONO_TYPE_VOID)
771 mono_mb_add_local (mb, sig->ret);
773 g_assert (sig->hasthis);
775 /* prev = addr of delegate */
776 mono_mb_emit_ldarg (mb, 0);
777 mono_mb_emit_stloc (mb, 0);
781 /* target = delegate->target */
782 mono_mb_emit_ldloc (mb, 0);
783 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
784 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
785 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoDelegate, target));
786 mono_mb_emit_byte (mb, CEE_ADD);
787 mono_mb_emit_byte (mb, CEE_LDIND_I);
788 mono_mb_emit_stloc (mb, 1);
790 /* mptr = delegate->method_ptr */
791 mono_mb_emit_ldloc (mb, 0);
792 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
793 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
794 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoDelegate, method_ptr));
795 mono_mb_emit_byte (mb, CEE_ADD);
796 mono_mb_emit_byte (mb, CEE_LDIND_I);
797 mono_mb_emit_stloc (mb, 2);
799 /* target == null ? */
800 mono_mb_emit_ldloc (mb, 1);
801 mono_mb_emit_byte (mb, CEE_BRTRUE);
803 mono_mb_emit_i4 (mb, 0);
805 /* emit static method call */
807 for (i = 0; i < sig->param_count; i++)
808 mono_mb_emit_ldarg (mb, i + 1);
810 mono_mb_emit_ldloc (mb, 2);
811 mono_mb_emit_byte (mb, CEE_CALLI);
812 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, static_sig));
814 if (sig->ret->type != MONO_TYPE_VOID)
815 mono_mb_emit_stloc (mb, 3);
817 mono_mb_emit_byte (mb, CEE_BR);
819 mono_mb_emit_i4 (mb, 0);
821 /* target != null, emit non static method call */
823 mono_mb_patch_addr (mb, pos [1], mb->pos - (pos [1] + 4));
824 mono_mb_emit_ldloc (mb, 1);
826 for (i = 0; i < sig->param_count; i++)
827 mono_mb_emit_ldarg (mb, i + 1);
829 mono_mb_emit_ldloc (mb, 2);
830 mono_mb_emit_byte (mb, CEE_CALLI);
831 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, sig));
833 if (sig->ret->type != MONO_TYPE_VOID)
834 mono_mb_emit_stloc (mb, 3);
836 mono_mb_patch_addr (mb, pos [2], mb->pos - (pos [2] + 4));
838 /* prev = delegate->prev */
839 mono_mb_emit_ldloc (mb, 0);
840 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
841 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
842 mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoMulticastDelegate, prev));
843 mono_mb_emit_byte (mb, CEE_ADD);
844 mono_mb_emit_byte (mb, CEE_LDIND_I);
845 mono_mb_emit_stloc (mb, 0);
847 /* if prev != null goto loop */
848 mono_mb_emit_ldloc (mb, 0);
849 mono_mb_emit_byte (mb, CEE_BRTRUE);
850 mono_mb_emit_i4 (mb, pos [0] - (mb->pos + 4));
852 if (sig->ret->type != MONO_TYPE_VOID)
853 mono_mb_emit_ldloc (mb, 3);
855 mono_mb_emit_byte (mb, CEE_RET);
857 res = mono_mb_create_method (mb, sig, 0);
860 g_hash_table_insert (cache, sig, res);
866 * generates IL code for the runtime invoke function
867 * MonoObject *runtime_invoke (MonoObject *this, void **params, MonoObject **exc)
869 * we also catch exceptions if exc != null
872 mono_marshal_get_runtime_invoke (MonoMethod *method)
874 MonoMethodSignature *sig, *csig;
875 MonoExceptionClause *clause;
876 MonoMethodHeader *header;
877 MonoMethodBuilder *mb;
880 static MonoString *string_dummy = NULL;
885 cache = method->klass->image->runtime_invoke_cache;
886 if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
889 /* to make it work with our special string constructors */
891 string_dummy = mono_string_new_wrapper ("dummy");
893 sig = method->signature;
895 sigsize = sizeof (MonoMethodSignature) + 3 * sizeof (MonoType *);
896 csig = g_malloc0 (sigsize);
898 csig->param_count = 3;
899 csig->ret = &mono_defaults.object_class->byval_arg;
900 csig->params [0] = &mono_defaults.object_class->byval_arg;
901 csig->params [1] = &mono_defaults.int_class->byval_arg;
902 csig->params [2] = &mono_defaults.int_class->byval_arg;
904 mb = mono_mb_new (method->klass, method->name);
905 mb->method->wrapper_type = MONO_WRAPPER_RUNTIME_INVOKE;
907 /* allocate local 0 (object) tmp */
908 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
909 /* allocate local 1 (object) exc */
910 mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
912 /* cond set *exc to null */
913 mono_mb_emit_byte (mb, CEE_LDARG_2);
914 mono_mb_emit_byte (mb, CEE_BRFALSE_S);
915 mono_mb_emit_byte (mb, 3);
916 mono_mb_emit_byte (mb, CEE_LDARG_2);
917 mono_mb_emit_byte (mb, CEE_LDNULL);
918 mono_mb_emit_byte (mb, CEE_STIND_I);
921 if (method->string_ctor) {
922 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
923 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
924 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, string_dummy));
926 mono_mb_emit_ldarg (mb, 0);
930 for (i = 0; i < sig->param_count; i++) {
931 MonoType *t = sig->params [i];
934 mono_mb_emit_ldarg (mb, 1);
936 mono_mb_emit_icon (mb, sizeof (gpointer) * i);
937 mono_mb_emit_byte (mb, CEE_ADD);
939 mono_mb_emit_byte (mb, CEE_LDIND_I);
944 type = sig->params [i]->type;
948 mono_mb_emit_byte (mb, CEE_LDIND_I1);
950 case MONO_TYPE_BOOLEAN:
952 mono_mb_emit_byte (mb, CEE_LDIND_U1);
955 mono_mb_emit_byte (mb, CEE_LDIND_I2);
959 mono_mb_emit_byte (mb, CEE_LDIND_U2);
961 #if SIZEOF_VOID_P == 4
965 mono_mb_emit_byte (mb, CEE_LDIND_I4);
967 #if SIZEOF_VOID_P == 4
971 mono_mb_emit_byte (mb, CEE_LDIND_U4);
974 mono_mb_emit_byte (mb, CEE_LDIND_R4);
977 mono_mb_emit_byte (mb, CEE_LDIND_R8);
979 #if SIZEOF_VOID_P == 8
985 mono_mb_emit_byte (mb, CEE_LDIND_I8);
987 case MONO_TYPE_STRING:
988 case MONO_TYPE_CLASS:
989 case MONO_TYPE_ARRAY:
991 case MONO_TYPE_SZARRAY:
992 case MONO_TYPE_OBJECT:
995 case MONO_TYPE_VALUETYPE:
996 if (t->data.klass->enumtype) {
997 type = t->data.klass->enum_basetype->type;
1000 g_assert_not_reached ();
1003 g_assert_not_reached ();
1007 if (method->string_ctor) {
1008 MonoMethodSignature *strsig;
1010 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1011 strsig = g_memdup (sig, sigsize);
1012 strsig->ret = &mono_defaults.string_class->byval_arg;
1014 mono_mb_emit_managed_call (mb, method, strsig);
1016 mono_mb_emit_managed_call (mb, method, NULL);
1018 switch (sig->ret->type) {
1019 case MONO_TYPE_VOID:
1020 if (!method->string_ctor)
1021 mono_mb_emit_byte (mb, CEE_LDNULL);
1035 case MONO_TYPE_VALUETYPE:
1036 /* box value types */
1037 mono_mb_emit_byte (mb, CEE_BOX);
1038 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_class_from_mono_type (sig->ret)));
1040 case MONO_TYPE_STRING:
1041 case MONO_TYPE_CLASS:
1042 case MONO_TYPE_ARRAY:
1043 case MONO_TYPE_SZARRAY:
1044 case MONO_TYPE_OBJECT:
1049 g_assert_not_reached ();
1052 mono_mb_emit_stloc (mb, 0);
1054 mono_mb_emit_byte (mb, CEE_LEAVE);
1056 mono_mb_emit_i4 (mb, 0);
1058 /* fixme: use a filter clause and only catch exceptions
1059 * when exc != null. With RETHROW we get wrong stack
1061 clause = g_new0 (MonoExceptionClause, 1);
1062 clause->flags = MONO_EXCEPTION_CLAUSE_NONE;
1063 clause->try_offset = 0;
1064 clause->try_len = mb->pos;
1065 clause->handler_offset = mb->pos;
1069 /* store exception */
1070 mono_mb_emit_stloc (mb, 1);
1072 mono_mb_emit_byte (mb, CEE_LDARG_2);
1073 mono_mb_emit_byte (mb, CEE_BRTRUE_S);
1074 mono_mb_emit_byte (mb, 2);
1075 mono_mb_emit_byte (mb, CEE_PREFIX1);
1076 mono_mb_emit_byte (mb, CEE_RETHROW);
1078 mono_mb_emit_byte (mb, CEE_LDARG_2);
1079 mono_mb_emit_ldloc (mb, 1);
1080 mono_mb_emit_byte (mb, CEE_STIND_I);
1082 mono_mb_emit_byte (mb, CEE_LEAVE);
1083 mono_mb_emit_i4 (mb, 0);
1085 clause->handler_len = mb->pos - clause->handler_offset;
1088 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
1089 mono_mb_emit_ldloc (mb, 0);
1090 mono_mb_emit_byte (mb, CEE_RET);
1092 res = mono_mb_create_method (mb, csig, 0);
1095 header = ((MonoMethodNormal *)res)->header;
1096 header->num_clauses = 1;
1097 header->clauses = clause;
1099 g_hash_table_insert (cache, method, res);
1105 * generates IL code to call managed methods from unmanaged code
1108 mono_marshal_get_managed_wrapper (MonoMethod *method, MonoObject *this)
1110 MonoMethodSignature *sig, *csig;
1111 MonoMethodBuilder *mb;
1116 g_assert (method != NULL);
1118 cache = method->klass->image->managed_wrapper_cache;
1119 if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
1122 sig = method->signature;
1124 mb = mono_mb_new (method->klass, method->name);
1125 mb->method->wrapper_type = MONO_WRAPPER_NATIVE_TO_MANAGED;
1127 /* we copy the signature, so that we can modify it */
1128 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1129 csig = g_memdup (sig, sigsize);
1132 /* fixme: howto handle this ? */
1136 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1137 mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
1138 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, this));
1143 g_assert_not_reached ();
1147 for (i = 0; i < sig->param_count; i++) {
1148 MonoType *t = sig->params [i];
1164 mono_mb_emit_ldarg (mb, i);
1166 case MONO_TYPE_STRING:
1167 csig->params [i] = &mono_defaults.int_class->byval_arg;
1168 mono_mb_emit_ldarg (mb, i);
1169 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1170 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
1171 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
1173 case MONO_TYPE_CLASS:
1174 case MONO_TYPE_ARRAY:
1175 case MONO_TYPE_SZARRAY:
1176 case MONO_TYPE_OBJECT:
1177 /* fixme: conversions ? */
1178 mono_mb_emit_ldarg (mb, i);
1181 g_warning ("type 0x%02x unknown", t->type);
1182 g_assert_not_reached ();
1186 mono_mb_emit_managed_call (mb, method, NULL);
1188 /* fixme: add return type conversions */
1190 mono_mb_emit_byte (mb, CEE_RET);
1192 res = mono_mb_create_method (mb, csig, 0);
1195 g_hash_table_insert (cache, method, res);
1201 * generates IL code for the pinvoke wrapper (the generated method
1202 * call the unamnage code in method->addr)
1205 mono_marshal_get_native_wrapper (MonoMethod *method)
1207 MonoMethodSignature *sig, *csig;
1208 MonoMethodBuilder *mb;
1212 gboolean pinvoke = FALSE;
1213 int i, argnum, *tmp_locals;
1216 g_assert (method != NULL);
1218 cache = method->klass->image->native_wrapper_cache;
1219 if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
1222 sig = method->signature;
1224 if (!(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
1225 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
1228 mb = mono_mb_new (method->klass, method->name);
1229 mb->method->wrapper_type = MONO_WRAPPER_MANAGED_TO_NATIVE;
1231 mb->method->save_lmf = 1;
1233 if (pinvoke && !method->addr)
1234 mono_lookup_pinvoke_call (method);
1236 if (!method->addr) {
1237 mono_mb_emit_exception (mb);
1238 res = mono_mb_create_method (mb, sig, 0);
1240 g_hash_table_insert (cache, method, res);
1244 /* we copy the signature, so that we can modify it */
1245 sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
1246 csig = g_memdup (sig, sigsize);
1248 if (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
1250 if (method->string_ctor)
1251 csig->ret = &mono_defaults.string_class->byval_arg;
1254 mono_mb_emit_byte (mb, CEE_LDARG_0);
1256 for (i = 0; i < sig->param_count; i++)
1257 mono_mb_emit_ldarg (mb, i + sig->hasthis);
1259 g_assert (method->addr);
1260 mono_mb_emit_native_call (mb, csig, method->addr);
1262 mono_mb_emit_byte (mb, CEE_RET);
1264 res = mono_mb_create_method (mb, csig, 0);
1266 g_hash_table_insert (cache, method, res);
1272 /* we allocate local for use with emit_struct_conv() */
1273 /* allocate local 0 (pointer) src_ptr */
1274 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1275 /* allocate local 1 (pointer) dst_ptr */
1276 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1277 /* allocate local 2 (pointer) as tmp/scratch storage */
1278 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1280 if (sig->ret->type != MONO_TYPE_VOID) {
1281 /* allocate local 3 to store the return value */
1282 mono_mb_add_local (mb, sig->ret);
1285 /* we first do all conversions */
1286 tmp_locals = alloca (sizeof (int) * sig->param_count);
1287 for (i = 0; i < sig->param_count; i ++) {
1288 MonoType *t = sig->params [i];
1290 argnum = i + sig->hasthis;
1292 /* allocate one tmp/scratch storage for each parameter */
1293 tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1296 case MONO_TYPE_VALUETYPE:
1297 klass = sig->params [i]->data.klass;
1298 if (klass->enumtype)
1301 /* store the address of the source into local variable 0 */
1302 mono_mb_emit_byte (mb, CEE_LDARGA);
1303 mono_mb_emit_i2 (mb, argnum);
1304 mono_mb_emit_byte (mb, CEE_STLOC_0);
1306 /* allocate space for the native struct and
1307 * store the address into local variable 1 (dest) */
1308 mono_mb_emit_icon (mb, mono_class_native_size (klass));
1309 mono_mb_emit_byte (mb, CEE_LOCALLOC);
1310 mono_mb_emit_stloc (mb, tmp_locals [i]);
1311 mono_mb_emit_ldloc (mb, tmp_locals [i]);
1312 mono_mb_emit_byte (mb, CEE_STLOC_1);
1314 /* emit valuetype convnversion code code */
1315 emit_struct_conv (mb, sig->params [i]->data.klass, FALSE);
1318 case MONO_TYPE_STRING:
1319 /* fixme: load the address instead */
1320 mono_mb_emit_ldarg (mb, argnum);
1321 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1322 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
1323 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
1324 mono_mb_emit_stloc (mb, tmp_locals [i]);
1326 case MONO_TYPE_CLASS:
1327 case MONO_TYPE_OBJECT:
1328 if (t->data.klass->delegate) {
1329 mono_mb_emit_ldarg (mb, argnum);
1330 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1331 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
1332 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_DEL_FTN);
1333 mono_mb_emit_stloc (mb, tmp_locals [i]);
1335 mono_mb_emit_ldarg (mb, argnum);
1336 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1337 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
1338 /* fixme: convert to what ? */
1339 mono_mb_emit_stloc (mb, tmp_locals [i]);
1345 /* push all arguments */
1348 mono_mb_emit_byte (mb, CEE_LDARG_0);
1350 for (i = 0; i < sig->param_count; i++) {
1351 MonoType *t = sig->params [i];
1353 argnum = i + sig->hasthis;
1356 mono_mb_emit_ldarg (mb, argnum);
1361 case MONO_TYPE_BOOLEAN:
1362 mono_mb_emit_ldarg (mb, argnum);
1377 mono_mb_emit_ldarg (mb, argnum);
1379 case MONO_TYPE_VALUETYPE:
1380 klass = sig->params [i]->data.klass;
1381 if (klass->enumtype) {
1382 mono_mb_emit_ldarg (mb, argnum);
1385 mono_mb_emit_ldloc (mb, tmp_locals [i]);
1386 //mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1387 //mono_mb_emit_byte (mb, CEE_MONO_LDOBJ);
1388 //mono_mb_emit_i4 (mb, mono_klass_native_size (klass));
1391 case MONO_TYPE_STRING:
1392 /* fixme: load the address instead */
1393 mono_mb_emit_ldloc (mb, tmp_locals [i]);
1395 case MONO_TYPE_CLASS:
1396 case MONO_TYPE_OBJECT:
1397 mono_mb_emit_ldloc (mb, tmp_locals [i]);
1399 case MONO_TYPE_CHAR:
1400 case MONO_TYPE_ARRAY:
1401 case MONO_TYPE_SZARRAY:
1402 case MONO_TYPE_TYPEDBYREF:
1403 case MONO_TYPE_FNPTR:
1405 g_warning ("type 0x%02x unknown", t->type);
1406 g_assert_not_reached ();
1410 /* call the native method */
1411 mono_mb_emit_native_call (mb, csig, method->addr);
1413 type = sig->ret->type;
1416 case MONO_TYPE_VOID:
1430 /* no conversions necessary */
1432 case MONO_TYPE_BOOLEAN:
1433 /* maybe we need to make sure that it fits within 8 bits */
1435 case MONO_TYPE_VALUETYPE:
1436 if (sig->ret->data.klass->enumtype) {
1437 type = sig->ret->data.klass->enum_basetype->type;
1440 g_warning ("generic valutype %s not handled", sig->ret->data.klass->name);
1441 g_assert_not_reached ();
1444 case MONO_TYPE_STRING:
1445 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
1446 mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
1447 mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_LPSTR_STR);
1449 case MONO_TYPE_ARRAY:
1450 case MONO_TYPE_SZARRAY:
1451 case MONO_TYPE_CLASS:
1452 case MONO_TYPE_OBJECT:
1453 /* fixme: we need conversions here */
1455 case MONO_TYPE_CHAR:
1456 case MONO_TYPE_TYPEDBYREF:
1457 case MONO_TYPE_FNPTR:
1459 g_warning ("return type 0x%02x unknown", sig->ret->type);
1460 g_assert_not_reached ();
1463 mono_mb_emit_byte (mb, CEE_RET);
1465 res = mono_mb_create_method (mb, sig, 0);
1468 g_hash_table_insert (cache, method, res);
1474 * generates IL code for StructureToPtr (object structure, IntPtr ptr, bool fDeleteOld)
1477 mono_marshal_get_struct_to_ptr (MonoClass *klass)
1479 MonoMethodBuilder *mb;
1480 static MonoMethod *stoptr = NULL;
1483 g_assert (klass != NULL);
1485 if (klass->str_to_ptr)
1486 return klass->str_to_ptr;
1489 stoptr = mono_find_method_by_name (mono_defaults.marshal_class, "StructureToPtr", 3);
1492 mb = mono_mb_new (stoptr->klass, stoptr->name);
1494 /* allocate local 0 (pointer) src_ptr */
1495 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1496 /* allocate local 1 (pointer) dst_ptr */
1497 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1498 /* allocate local 2 (pointer) as tmp/scratch storage */
1499 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1501 /* initialize src_ptr to point to the start of object data */
1502 mono_mb_emit_byte (mb, CEE_LDARG_0);
1503 mono_mb_emit_icon (mb, sizeof (MonoObject));
1504 mono_mb_emit_byte (mb, CEE_ADD);
1505 mono_mb_emit_byte (mb, CEE_STLOC_0);
1507 /* initialize dst_ptr */
1508 mono_mb_emit_byte (mb, CEE_LDARG_1);
1509 mono_mb_emit_byte (mb, CEE_STLOC_1);
1511 emit_struct_conv (mb, klass, FALSE);
1513 mono_mb_emit_byte (mb, CEE_RET);
1515 res = mono_mb_create_method (mb, stoptr->signature, 0);
1518 klass->str_to_ptr = res;
1523 * generates IL code for PtrToStructure (IntPtr src, object structure)
1526 mono_marshal_get_ptr_to_struct (MonoClass *klass)
1528 MonoMethodBuilder *mb;
1529 static MonoMethod *ptostr = NULL;
1532 g_assert (klass != NULL);
1534 if (klass->ptr_to_str)
1535 return klass->ptr_to_str;
1538 ptostr = mono_find_method_by_name (mono_defaults.marshal_class, "PtrToStructure", 2);
1541 mb = mono_mb_new (ptostr->klass, ptostr->name);
1543 /* allocate local 0 (pointer) src_ptr */
1544 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1545 /* allocate local 1 (pointer) dst_ptr */
1546 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1547 /* allocate local 2 (pointer) as tmp/scratch storage */
1548 mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
1550 /* initialize src_ptr to point to the start of object data */
1551 mono_mb_emit_byte (mb, CEE_LDARG_0);
1552 mono_mb_emit_byte (mb, CEE_STLOC_0);
1554 /* initialize dst_ptr */
1555 mono_mb_emit_byte (mb, CEE_LDARG_1);
1556 mono_mb_emit_icon (mb, sizeof (MonoObject));
1557 mono_mb_emit_byte (mb, CEE_ADD);
1558 mono_mb_emit_byte (mb, CEE_STLOC_1);
1560 emit_struct_conv (mb, klass, TRUE);
1562 mono_mb_emit_byte (mb, CEE_RET);
1564 res = mono_mb_create_method (mb, ptostr->signature, 0);
1567 klass->ptr_to_str = res;
1571 /* FIXME: on win32 we should probably use GlobalAlloc(). */
1573 mono_marshal_alloc (gpointer size) {
1574 return g_try_malloc ((gulong)size);
1578 mono_marshal_free (gpointer ptr) {
1583 mono_marshal_realloc (gpointer ptr, gpointer size) {
1584 return g_try_realloc (ptr, (gulong)size);
1588 mono_marshal_string_array (MonoArray *array)
1596 len = mono_array_length (array);
1598 result = g_malloc (sizeof (char*) * len);
1599 for (i = 0; i < len; ++i) {
1600 MonoString *s = (MonoString*)mono_array_get (array, gpointer, i);
1601 result [i] = s ? mono_string_to_utf8 (s): NULL;
1607 ves_icall_System_Runtime_InteropServices_Marshal_copy_to_unmanaged (MonoArray *src, gint32 start_index,
1608 gpointer dest, gint32 length)
1613 MONO_CHECK_ARG_NULL (src);
1614 MONO_CHECK_ARG_NULL (dest);
1616 g_assert (src->obj.vtable->klass->rank == 1);
1617 g_assert (start_index >= 0 && start_index < mono_array_length (src));
1618 g_assert (start_index + length <= mono_array_length (src));
1620 element_size = mono_array_element_size (src->obj.vtable->klass);
1622 source_addr = mono_array_addr_with_size (src, element_size, start_index);
1624 memcpy (dest, source_addr, length * element_size);
1628 ves_icall_System_Runtime_InteropServices_Marshal_copy_from_unmanaged (gpointer src, gint32 start_index,
1629 MonoArray *dest, gint32 length)
1634 MONO_CHECK_ARG_NULL (src);
1635 MONO_CHECK_ARG_NULL (dest);
1637 g_assert (dest->obj.vtable->klass->rank == 1);
1638 g_assert (start_index >= 0 && start_index < mono_array_length (dest));
1639 g_assert (start_index + length <= mono_array_length (dest));
1641 element_size = mono_array_element_size (dest->obj.vtable->klass);
1643 dest_addr = mono_array_addr_with_size (dest, element_size, start_index);
1645 memcpy (dest_addr, src, length * element_size);
1649 ves_icall_System_Runtime_InteropServices_Marshal_ReadIntPtr (gpointer ptr, gint32 offset)
1652 return *(gpointer*)(p + offset);
1656 ves_icall_System_Runtime_InteropServices_Marshal_ReadByte (gpointer ptr, gint32 offset)
1659 return *(unsigned char*)(p + offset);
1663 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt16 (gpointer ptr, gint32 offset)
1666 return *(gint16*)(p + offset);
1670 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt32 (gpointer ptr, gint32 offset)
1673 return *(gint32*)(p + offset);
1677 ves_icall_System_Runtime_InteropServices_Marshal_ReadInt64 (gpointer ptr, gint32 offset)
1680 return *(gint64*)(p + offset);
1684 ves_icall_System_Runtime_InteropServices_Marshal_WriteByte (gpointer ptr, gint32 offset, unsigned char val)
1687 *(unsigned char*)(p + offset) = val;
1691 ves_icall_System_Runtime_InteropServices_Marshal_WriteIntPtr (gpointer ptr, gint32 offset, gpointer val)
1694 *(gpointer*)(p + offset) = val;
1698 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt16 (gpointer ptr, gint32 offset, gint16 val)
1701 *(gint16*)(p + offset) = val;
1705 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt32 (gpointer ptr, gint32 offset, gint32 val)
1708 *(gint32*)(p + offset) = val;
1712 ves_icall_System_Runtime_InteropServices_Marshal_WriteInt64 (gpointer ptr, gint32 offset, gint64 val)
1715 *(gint64*)(p + offset) = val;
1719 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAuto (gpointer ptr)
1721 MonoDomain *domain = mono_domain_get ();
1723 return mono_string_new (domain, (char *)ptr);
1727 ves_icall_System_Runtime_InteropServices_Marshal_GetLastWin32Error (void)
1729 return (GetLastError ());
1733 ves_icall_System_Runtime_InteropServices_Marshal_SizeOf (MonoReflectionType *rtype)
1737 MONO_CHECK_ARG_NULL (rtype);
1739 klass = mono_class_from_mono_type (rtype->type);
1741 return mono_class_native_size (klass);
1745 ves_icall_System_Runtime_InteropServices_Marshal_StructureToPtr (MonoObject *obj, gpointer dst, MonoBoolean delete_old)
1750 MONO_CHECK_ARG_NULL (obj);
1751 MONO_CHECK_ARG_NULL (dst);
1753 method = mono_marshal_get_struct_to_ptr (obj->vtable->klass);
1757 pa [2] = &delete_old;
1759 mono_runtime_invoke (method, NULL, pa, NULL);
1763 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (gpointer src, MonoObject *dst)
1768 MONO_CHECK_ARG_NULL (src);
1769 MONO_CHECK_ARG_NULL (dst);
1771 method = mono_marshal_get_ptr_to_struct (dst->vtable->klass);
1776 mono_runtime_invoke (method, NULL, pa, NULL);