2 * object.c: Object creation for the Mono runtime
5 * Miguel de Icaza (miguel@ximian.com)
7 * (C) 2001 Ximian, Inc.
14 #include <mono/metadata/mono-endian.h>
15 #include <mono/metadata/tabledefs.h>
16 #include <mono/metadata/tokentype.h>
17 #include <mono/metadata/loader.h>
18 #include <mono/metadata/object.h>
19 #include <mono/metadata/gc.h>
20 #include <mono/metadata/appdomain.h>
27 /* next object id for object hashcode */
28 static guint32 uoid = 0;
31 mono_runtime_object_init (MonoObject *this)
34 MonoMethod *method = NULL;
35 MonoClass *klass = this->vtable->klass;
37 for (i = 0; i < klass->method.count; ++i) {
38 if (!strcmp (".ctor", klass->methods [i]->name) &&
39 klass->methods [i]->signature->param_count == 0) {
40 method = klass->methods [i];
47 mono_runtime_invoke (method, this, NULL);
52 * @klass: klass that needs to be initialized
54 * This routine calls the class constructor for @class.
57 mono_runtime_class_init (MonoClass *klass)
61 for (i = 0; i < klass->method.count; ++i) {
62 MonoMethod *method = klass->methods [i];
63 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
64 (strcmp (".cctor", method->name) == 0)) {
65 mono_runtime_invoke (method, NULL, NULL);
69 /* No class constructor found */
73 default_trampoline (MonoMethod *method)
79 default_remoting_trampoline (MonoMethod *method)
81 g_error ("remoting not installed");
85 static MonoTrampoline arch_create_jit_trampoline = default_trampoline;
86 static MonoTrampoline arch_create_remoting_trampoline = default_remoting_trampoline;
89 mono_install_trampoline (MonoTrampoline func)
91 arch_create_jit_trampoline = func? func: default_trampoline;
95 mono_install_remoting_trampoline (MonoTrampoline func)
97 arch_create_remoting_trampoline = func? func: default_remoting_trampoline;
100 #if 0 && HAVE_BOEHM_GC
102 vtable_finalizer (void *obj, void *data) {
103 g_print ("%s finalized (%p)\n", (char*)data, obj);
109 * @domain: the application domain
110 * @class: the class to initialize
112 * VTables are domain specific because we create domain specific code, and
113 * they contain the domain specific static class data.
116 mono_class_vtable (MonoDomain *domain, MonoClass *class)
120 MonoClassField *field;
122 guint32 cols [MONO_CONSTANT_SIZE];
129 /* can interfaces have static fields? */
130 if (class->flags & TYPE_ATTRIBUTE_INTERFACE)
131 g_assert_not_reached ();
133 mono_domain_lock (domain);
134 if ((vt = mono_g_hash_table_lookup (domain->class_vtable_hash, class))) {
135 mono_domain_unlock (domain);
140 mono_class_init (class);
142 // mono_stats.used_class_count++;
143 // mono_stats.class_vtable_size += sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
145 vt = mono_mempool_alloc0 (domain->mp, sizeof (MonoVTable) +
146 class->vtable_size * sizeof (gpointer));
150 if (class->class_size) {
152 vt->data = GC_malloc (class->class_size + 8);
153 /*vt->data = GC_debug_malloc (class->class_size + 8, class->name, 2);*/
154 /*GC_register_finalizer (vt->data, vtable_finalizer, class->name, NULL, NULL);*/
155 mono_g_hash_table_insert (domain->static_data_hash, class, vt->data);
157 vt->data = mono_mempool_alloc0 (domain->mp, class->class_size + 8);
160 // mono_stats.class_static_data_size += class->class_size + 8;
163 for (i = class->field.first; i < class->field.last; ++i) {
164 field = &class->fields [i - class->field.first];
165 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
167 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
169 cindex = mono_metadata_get_constant_index (class->image, MONO_TOKEN_FIELD_DEF | (i + 1));
171 g_warning ("constant for field %s not found", field->name);
174 mono_metadata_decode_row (&class->image->tables [MONO_TABLE_CONSTANT], cindex - 1, cols, MONO_CONSTANT_SIZE);
175 p = mono_metadata_blob_heap (class->image, cols [MONO_CONSTANT_VALUE]);
176 len = mono_metadata_decode_blob_size (p, &p);
177 t = (char*)vt->data + field->offset;
178 /* should we check that the type matches? */
179 switch (cols [MONO_CONSTANT_TYPE]) {
180 case MONO_TYPE_BOOLEAN:
188 guint16 *val = (guint16*)t;
194 guint32 *val = (guint32*)t;
200 guint64 *val = (guint64*)t;
205 float *val = (float*)t;
210 double *val = (double*)t;
214 case MONO_TYPE_STRING: {
215 //gpointer *val = (gpointer*)t;
216 //*val = mono_string_new_utf16 (domain, (const guint16*)p, len/2);
219 case MONO_TYPE_CLASS:
220 /* nothing to do, we malloc0 the data and the value can be 0 only */
223 g_warning ("type 0x%02x should not be in constant table", cols [MONO_CONSTANT_TYPE]);
227 vt->max_interface_id = class->max_interface_id;
229 vt->interface_offsets = mono_mempool_alloc0 (domain->mp,
230 sizeof (gpointer) * (class->max_interface_id + 1));
232 /* initialize interface offsets */
233 for (k = class; k ; k = k->parent) {
234 for (i = 0; i < k->interface_count; i++) {
236 MonoClass *ic = k->interfaces [i];
237 slot = class->interface_offsets [ic->interface_id];
238 vt->interface_offsets [ic->interface_id] = &vt->vtable [slot];
242 /* initialize vtable */
243 for (i = 0; i < class->vtable_size; ++i) {
246 if ((cm = class->vtable [i]))
247 vt->vtable [i] = arch_create_jit_trampoline (cm);
250 mono_g_hash_table_insert (domain->class_vtable_hash, class, vt);
251 mono_domain_unlock (domain);
253 mono_runtime_class_init (class);
259 * mono_class_proxy_vtable:
260 * @domain: the application domain
261 * @class: the class to proxy
263 * Creates a vtable for transparent proxies. It is basically
264 * a copy of the real vtable of @class, but all function pointers invoke
265 * the remoting functions, and vtable->klass points to the
266 * transparent proxy class, and not to @class.
269 mono_class_proxy_vtable (MonoDomain *domain, MonoClass *class)
271 MonoVTable *vt, *pvt;
274 if ((pvt = mono_g_hash_table_lookup (domain->proxy_vtable_hash, class)))
277 vt = mono_class_vtable (domain, class);
278 vtsize = sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer);
280 // mono_stats.class_vtable_size += vtsize;
282 pvt = mono_mempool_alloc (domain->mp, vtsize);
283 memcpy (pvt, vt, vtsize);
285 pvt->klass = mono_defaults.transparent_proxy_class;
287 /* initialize vtable */
288 for (i = 0; i < class->vtable_size; ++i) {
291 if ((cm = class->vtable [i]))
292 pvt->vtable [i] = arch_create_remoting_trampoline (cm);
295 mono_g_hash_table_insert (domain->proxy_vtable_hash, class, pvt);
300 static MonoInvokeFunc default_mono_runtime_invoke = NULL;
303 mono_runtime_invoke (MonoMethod *method, void *obj, void **params)
305 if (!default_mono_runtime_invoke) {
306 g_error ("runtime invoke called on uninitialized runtime");
309 return default_mono_runtime_invoke (method, obj, params);
312 static MonoArray* main_args;
315 mono_runtime_get_main_args (void)
321 * Execute a standard Main() method (argc/argv contains the
322 * executable name). This method also sets the command line argument value
323 * needed by System.Environment.
326 mono_runtime_run_main (MonoMethod *method, int argc, char* argv[])
329 MonoArray *args = NULL;
330 MonoDomain *domain = mono_domain_get ();
332 main_args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
333 for (i = 0; i < argc; ++i) {
334 MonoString *arg = mono_string_new (domain, argv [i]);
335 mono_array_set (main_args, gpointer, i, arg);
339 if (method->signature->param_count) {
340 args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
341 for (i = 0; i < argc; ++i) {
342 MonoString *arg = mono_string_new (domain, argv [i]);
343 mono_array_set (args, gpointer, i, arg);
347 return mono_runtime_exec_main (method, args);
351 * Execute a standard Main() method (args doesn't contain the
355 mono_runtime_exec_main (MonoMethod *method, MonoArray *args)
361 /* FIXME: check signature of method */
362 if (method->signature->ret->type == MONO_TYPE_I4) {
364 res = mono_runtime_invoke (method, NULL, pa);
365 return *(guint32 *)((char *)res + sizeof (MonoObject));
367 mono_runtime_invoke (method, NULL, pa);
373 mono_install_runtime_invoke (MonoInvokeFunc func)
375 default_mono_runtime_invoke = func;
379 mono_runtime_invoke_array (MonoMethod *method, void *obj, MonoArray *params)
381 MonoMethodSignature *sig = method->signature;
385 if (NULL != params) {
386 pa = alloca (sizeof (gpointer) * mono_array_length (params));
387 for (i = 0; i < mono_array_length (params); i++) {
388 if (sig->params [i]->byref) {
392 switch (sig->params [i]->type) {
395 case MONO_TYPE_BOOLEAN:
405 case MONO_TYPE_VALUETYPE:
406 pa [i] = (char *)(((gpointer *)params->vector)[i]) + sizeof (MonoObject);
408 case MONO_TYPE_STRING:
409 case MONO_TYPE_OBJECT:
410 case MONO_TYPE_CLASS:
411 pa [i] = (char *)(((gpointer *)params->vector)[i]);
414 g_error ("type 0x%x not handled in ves_icall_InternalInvoke", sig->params [i]->type);
419 if (!strcmp (method->name, ".ctor")) {
420 obj = mono_object_new (mono_domain_get (), method->klass);
421 mono_runtime_invoke (method, obj, pa);
424 return mono_runtime_invoke (method, obj, pa);
428 * mono_object_allocate:
429 * @size: number of bytes to allocate
431 * This is a very simplistic routine until we have our GC-aware
434 * Returns: an allocated object of size @size, or NULL on failure.
437 mono_object_allocate (size_t size)
440 /* if this is changed to GC_debug_malloc(), we need to change also metadata/gc.c */
441 void *o = GC_malloc (size);
443 void *o = calloc (1, size);
452 * Frees the memory used by the object. Debugging purposes
453 * only, as we will have our GC system.
456 mono_object_free (MonoObject *o)
459 g_error ("mono_object_free called with boehm gc.");
461 MonoClass *c = o->vtable->klass;
463 memset (o, 0, c->instance_size);
470 * @klass: the class of the object that we want to create
472 * Returns: A newly created object whose definition is
473 * looked up using @klass
476 mono_object_new (MonoDomain *domain, MonoClass *klass)
478 return mono_object_new_specific (mono_class_vtable (domain, klass));
482 * mono_object_new_specific:
483 * @vtable: the vtable of the object that we want to create
485 * Returns: A newly created object with class and domain specified
489 mono_object_new_specific (MonoVTable *vtable)
493 mono_stats.new_object_count++; /* thread safe? */
495 /* if the returned pointer is not the same as the address returned by GC_malloc(),
496 * we need to change also metadata/gc.c to take into account the new offset.
498 if (vtable->klass->ghcimpl)
499 o = mono_object_allocate (vtable->klass->instance_size);
502 t = mono_object_allocate (vtable->klass->instance_size + 4);
504 o = (MonoObject *)(++t);
507 if (vtable->klass->has_finalize)
508 mono_object_register_finalizer (o);
514 * mono_object_new_from_token:
515 * @image: Context where the type_token is hosted
516 * @token: a token of the type that we want to create
518 * Returns: A newly created object whose definition is
519 * looked up using @token in the @image image
522 mono_object_new_from_token (MonoDomain *domain, MonoImage *image, guint32 token)
526 class = mono_class_get (image, token);
528 return mono_object_new (domain, class);
534 * @obj: the object to clone
536 * Returns: A newly created object who is a shallow copy of @obj
539 mono_object_clone (MonoObject *obj)
544 size = obj->vtable->klass->instance_size;
545 o = mono_object_allocate (size);
547 memcpy (o, obj, size);
549 if (obj->vtable->klass->has_finalize)
550 mono_object_register_finalizer (o);
556 * @array: the array to clone
558 * Returns: A newly created array who is a shallow copy of @array
561 mono_array_clone (MonoArray *array)
566 MonoClass *klass = array->obj.vtable->klass;
568 if (array->bounds == NULL) {
569 size = mono_array_length (array);
570 o = mono_array_new_full (((MonoObject *)array)->vtable->domain,
573 size *= mono_array_element_size (klass);
574 memcpy (o, array, sizeof (MonoArray) + size);
579 sizes = alloca (klass->rank * sizeof(guint32) * 2);
580 size = mono_array_element_size (klass);
581 for (i = 0; i < klass->rank; ++i) {
582 sizes [i] = array->bounds [i].length;
583 size *= array->bounds [i].length;
584 sizes [i + klass->rank] = array->bounds [i].lower_bound;
586 o = mono_array_new_full (((MonoObject *)array)->vtable->domain,
587 klass, sizes, sizes + klass->rank);
588 memcpy (o, array, sizeof(MonoArray) + size);
594 * mono_array_new_full:
595 * @domain: domain where the object is created
596 * @array_class: array class
597 * @lengths: lengths for each dimension in the array
598 * @lower_bounds: lower bounds for each dimension in the array (may be NULL)
600 * This routine creates a new array objects with the given dimensions,
601 * lower bounds and type.
604 mono_array_new_full (MonoDomain *domain, MonoClass *array_class,
605 guint32 *lengths, guint32 *lower_bounds)
607 guint32 byte_len, len;
610 MonoArrayBounds *bounds;
613 if (!array_class->inited)
614 mono_class_init (array_class);
616 byte_len = mono_array_element_size (array_class);
619 if (array_class->rank == 1 &&
620 (lower_bounds == NULL || lower_bounds [0] == 0)) {
625 bounds = GC_malloc (sizeof (MonoArrayBounds) * array_class->rank);
627 bounds = g_malloc0 (sizeof (MonoArrayBounds) * array_class->rank);
629 for (i = 0; i < array_class->rank; ++i) {
630 bounds [i].length = lengths [i];
635 for (i = 0; i < array_class->rank; ++i)
636 bounds [i].lower_bound = lower_bounds [i];
641 * Following three lines almost taken from mono_object_new ():
642 * they need to be kept in sync.
644 o = mono_object_allocate (sizeof (MonoArray) + byte_len);
647 o->vtable = mono_class_vtable (domain, array_class);
649 array = (MonoArray*)o;
651 array->bounds = bounds;
652 array->max_length = len;
659 * @domain: domain where the object is created
660 * @eclass: element class
661 * @n: number of array elements
663 * This routine creates a new szarray with @n elements of type @eclass.
666 mono_array_new (MonoDomain *domain, MonoClass *eclass, guint32 n)
670 ac = mono_array_class_get (&eclass->byval_arg, 1);
671 g_assert (ac != NULL);
673 return mono_array_new_specific (mono_class_vtable (domain, ac), n);
677 * mono_array_new_specific:
678 * @vtable: a vtable in the appropriate domain for an initialized class
679 * @n: number of array elements
681 * This routine is a fast alternative to mono_array_new() for code which
682 * can be sure about the domain it operates in.
685 mono_array_new_specific (MonoVTable *vtable, guint32 n)
691 byte_len = n * mono_array_element_size (vtable->klass);
692 o = mono_object_allocate (sizeof (MonoArray) + byte_len);
705 * mono_string_new_utf16:
706 * @text: a pointer to an utf16 string
707 * @len: the length of the string
709 * Returns: A newly created string object which contains @text.
712 mono_string_new_utf16 (MonoDomain *domain, const guint16 *text, gint32 len)
716 s = mono_string_new_size (domain, len);
717 g_assert (s != NULL);
719 memcpy (mono_string_chars (s), text, len * 2);
725 * mono_string_new_size:
726 * @text: a pointer to an utf16 string
727 * @len: the length of the string
729 * Returns: A newly created string object of @len
732 mono_string_new_size (MonoDomain *domain, gint32 len)
737 * enable to get a good speedup: we still need to figure out
738 * how the sync structure is freed.
741 s = GC_malloc_atomic (sizeof (MonoString) + ((len + 1) * 2));
742 s->object.synchronisation = 0;
743 mono_string_chars (s) [len] = 0;
745 s = (MonoString*)mono_object_allocate (sizeof (MonoString) + ((len + 1) * 2));
750 s->object.vtable = mono_class_vtable (domain, mono_defaults.string_class);
757 * mono_string_new_len:
758 * @text: a pointer to an utf8 string
759 * @length: number of bytes in @text to consider
761 * Returns: A newly created string object which contains @text.
764 mono_string_new_len (MonoDomain *domain, const char *text, guint length)
766 GError *error = NULL;
767 MonoString *o = NULL;
772 ut = g_utf8_to_utf16 (text, length, NULL, &items_written, &error);
775 o = mono_string_new_utf16 (domain, ut, items_written);
777 g_error_free (error);
786 * @text: a pointer to an utf8 string
788 * Returns: A newly created string object which contains @text.
791 mono_string_new (MonoDomain *domain, const char *text)
793 GError *error = NULL;
794 MonoString *o = NULL;
801 ut = g_utf8_to_utf16 (text, l, NULL, &items_written, &error);
804 o = mono_string_new_utf16 (domain, ut, items_written);
806 g_error_free (error);
814 * mono_string_new_wrapper:
815 * @text: pointer to utf8 characters.
817 * Helper function to create a string object from @text in the current domain.
820 mono_string_new_wrapper (const char *text)
822 MonoDomain *domain = mono_domain_get ();
824 return mono_string_new (domain, text);
829 * @class: the class of the value
830 * @value: a pointer to the unboxed data
832 * Returns: A newly created object which contains @value.
835 mono_value_box (MonoDomain *domain, MonoClass *class, gpointer value)
840 g_assert (class->valuetype);
842 size = mono_class_instance_size (class);
843 res = mono_object_allocate (size);
844 res->vtable = mono_class_vtable (domain, class);
846 size = size - sizeof (MonoObject);
848 memcpy ((char *)res + sizeof (MonoObject), value, size);
850 if (class->has_finalize)
851 mono_object_register_finalizer (res);
856 * mono_object_isinst:
858 * @klass: a pointer to a class
860 * Returns: @obj if @obj is derived from @klass
863 mono_object_isinst (MonoObject *obj, MonoClass *klass)
875 mono_class_init (klass);
877 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
878 if ((klass->interface_id <= oklass->max_interface_id) &&
879 vt->interface_offsets [klass->interface_id])
882 if (oklass == mono_defaults.transparent_proxy_class) {
883 /* fixme: add check for IRemotingTypeInfo */
884 oklass = ((MonoTransparentProxy *)obj)->klass;
887 if (oklass->rank == klass->rank &&
888 (oklass->element_class->baseval - klass->element_class->baseval) <=
889 klass->element_class->diffval)
892 } else if ((oklass->baseval - klass->baseval) <= klass->diffval)
900 mono_string_is_interned_lookup (MonoString *str, int insert)
902 MonoGHashTable *ldstr_table;
905 char *ins = g_malloc (4 + str->length * 2);
909 /* Encode the length */
911 mono_metadata_encode_value (2 * str->length, p, &p);
914 mono_metadata_encode_value (bloblen + 2 * str->length, p, &p);
915 bloblen = (p - ins) + 2 * str->length;
917 * ins is stored in the hash table as a key and needs to have the same
918 * representation as in the metadata: we swap the character bytes on big
921 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
924 char *p2 = mono_string_chars (str);
925 for (i = 0; i < str->length; ++i) {
932 memcpy (p, mono_string_chars (str), str->length * 2);
934 domain = ((MonoObject *)str)->vtable->domain;
935 ldstr_table = domain->ldstr_table;
936 mono_domain_lock (domain);
937 if ((res = mono_g_hash_table_lookup (ldstr_table, ins))) {
938 mono_domain_unlock (domain);
943 mono_g_hash_table_insert (ldstr_table, ins, str);
944 mono_domain_unlock (domain);
947 mono_domain_unlock (domain);
953 mono_string_is_interned (MonoString *o)
955 return mono_string_is_interned_lookup (o, FALSE);
959 mono_string_intern (MonoString *str)
961 return mono_string_is_interned_lookup (str, TRUE);
966 * @domain: the domain where the string will be used.
967 * @image: a metadata context
968 * @idx: index into the user string table.
970 * Implementation for the ldstr opcode.
973 mono_ldstr (MonoDomain *domain, MonoImage *image, guint32 idx)
975 const char *str, *sig;
979 sig = str = mono_metadata_user_string (image, idx);
981 mono_domain_lock (domain);
982 if ((o = mono_g_hash_table_lookup (domain->ldstr_table, sig))) {
983 mono_domain_unlock (domain);
987 len2 = mono_metadata_decode_blob_size (str, &str);
990 o = mono_string_new_utf16 (domain, (guint16*)str, len2);
991 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
994 guint16 *p2 = (guint16*)mono_string_chars (o);
995 for (i = 0; i < len2; ++i) {
996 *p2 = GUINT16_FROM_LE (*p2);
1001 mono_g_hash_table_insert (domain->ldstr_table, (gpointer)sig, o);
1002 mono_domain_unlock (domain);
1008 * mono_string_to_utf8:
1009 * @s: a System.String
1011 * Return the UTF8 representation for @s.
1012 * the resulting buffer nedds to be freed with g_free().
1015 mono_string_to_utf8 (MonoString *s)
1018 GError *error = NULL;
1020 g_assert (s != NULL);
1023 return g_strdup ("");
1025 as = g_utf16_to_utf8 (mono_string_chars (s), s->length, NULL, NULL, &error);
1027 g_warning (error->message);
1033 * mono_string_to_utf16:
1036 * Return an null-terminated array of the utf-16 chars
1037 * contained in @s. The result must be freed with g_free().
1038 * This is a temporary helper until our string implementation
1039 * is reworked to always include the null terminating char.
1042 mono_string_to_utf16 (MonoString *s)
1046 g_assert (s != NULL);
1048 as = g_malloc ((s->length * 2) + 2);
1049 as [(s->length * 2)] = '\0';
1050 as [(s->length * 2) + 1] = '\0';
1053 return (gunichar2 *)(as);
1056 memcpy (as, mono_string_chars(s), s->length * 2);
1058 return (gunichar2 *)(as);
1062 default_ex_handler (MonoException *ex)
1064 MonoObject *o = (MonoObject*)ex;
1065 g_error ("Exception %s.%s raised in C code", o->vtable->klass->name_space, o->vtable->klass->name);
1068 static MonoExceptionFunc ex_handler = default_ex_handler;
1071 mono_install_handler (MonoExceptionFunc func)
1073 ex_handler = func? func: default_ex_handler;
1077 * mono_raise_exception:
1078 * @ex: exception object
1080 * Signal the runtime that the exception @ex has been raised in unmanaged code.
1083 mono_raise_exception (MonoException *ex)
1089 mono_wait_handle_new (MonoDomain *domain, HANDLE handle)
1091 MonoWaitHandle *res;
1093 res = (MonoWaitHandle *)mono_object_new (domain, mono_defaults.waithandle_class);
1095 res->handle = handle;
1101 mono_async_result_new (MonoDomain *domain, HANDLE handle, MonoObject *state, gpointer data)
1103 MonoAsyncResult *res;
1105 res = (MonoAsyncResult *)mono_object_new (domain, mono_defaults.asyncresult_class);
1108 res->async_state = state;
1109 res->handle = (MonoObject *)mono_wait_handle_new (domain, handle);
1110 res->sync_completed = FALSE;
1111 res->completed = FALSE;
1117 mono_message_init (MonoDomain *domain,
1118 MonoMethodMessage *this,
1119 MonoReflectionMethod *method,
1120 MonoArray *out_args)
1122 MonoMethodSignature *sig = method->method->signature;
1128 this->method = method;
1130 this->args = mono_array_new (domain, mono_defaults.object_class, sig->param_count);
1131 this->arg_types = mono_array_new (domain, mono_defaults.byte_class, sig->param_count);
1133 names = g_new (char *, sig->param_count);
1134 mono_method_get_param_names (method->method, (const char **) names);
1135 this->names = mono_array_new (domain, mono_defaults.string_class, sig->param_count);
1137 for (i = 0; i < sig->param_count; i++) {
1138 name = mono_string_new (domain, names [i]);
1139 mono_array_set (this->names, gpointer, i, name);
1144 for (i = 0, j = 0; i < sig->param_count; i++) {
1146 if (sig->params [i]->byref) {
1148 gpointer arg = mono_array_get (out_args, gpointer, j);
1149 mono_array_set (this->args, gpointer, i, arg);
1153 if (sig->params [i]->attrs & PARAM_ATTRIBUTE_IN)
1159 mono_array_set (this->arg_types, guint8, i, arg_type);
1164 * mono_remoting_invoke:
1165 * @real_proxy: pointer to a RealProxy object
1166 * @msg: The MonoMethodMessage to execute
1167 * @exc: used to store exceptions
1168 * @out_args: used to store output arguments
1170 * This is used to call RealProxy::Invoke(). RealProxy::Invoke() returns an
1171 * IMessage interface and it is not trivial to extract results from there. So
1172 * we call an helper method PrivateInvoke instead of calling
1173 * RealProxy::Invoke() directly.
1175 * Returns: the result object.
1178 mono_remoting_invoke (MonoObject *real_proxy, MonoMethodMessage *msg,
1179 MonoObject **exc, MonoArray **out_args)
1181 static MonoMethod *im = NULL;
1184 //static MonoObject *(*invoke) (gpointer, gpointer, MonoObject **, MonoArray **) = NULL;
1186 /* fixme: make this domain dependent */
1191 klass = mono_defaults.real_proxy_class;
1193 for (i = 0; i < klass->method.count; ++i) {
1194 if (!strcmp ("PrivateInvoke", klass->methods [i]->name) &&
1195 klass->methods [i]->signature->param_count == 4) {
1196 im = klass->methods [i];
1204 pa [0] = real_proxy;
1209 return mono_runtime_invoke (im, NULL, pa);
1213 mono_message_invoke (MonoObject *target, MonoMethodMessage *msg,
1214 MonoObject **exc, MonoArray **out_args)
1216 if (target && target->vtable->klass == mono_defaults.transparent_proxy_class) {
1218 return mono_remoting_invoke ((MonoObject *)((MonoTransparentProxy *)target)->rp,
1219 msg, exc, out_args);
1222 MonoDomain *domain = mono_domain_get ();
1223 MonoMethod *method = msg->method->method;
1224 MonoMethodSignature *sig = method->signature;
1225 int i, j, outarg_count = 0;
1227 for (i = 0; i < sig->param_count; i++) {
1228 if (sig->params [i]->byref)
1232 *out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
1235 for (i = 0, j = 0; i < sig->param_count; i++) {
1236 if (sig->params [i]->byref) {
1238 arg = mono_array_get (msg->args, gpointer, i);
1239 mono_array_set (*out_args, gpointer, j, arg);
1244 return mono_runtime_invoke_array (method, target, msg->args);