mono embedding, call a C# generic method from C
14:03 08 Mar 2014

I am having trouble figuring out how to call generic method (both static and non-static) from C.

The biggest culprit is that calling generic methods is essentially undocumented, there are no examples in the mono repository but there's a mention that this is supposedly possible in the docs:

If you want to invoke generic methods, you must call the method on the "inflated" class, which you can obtain from the mono_object_get_class()


MonoClass *clazz;
MonoMethod *method;

clazz = mono_object_get_class (obj);

/*
 * If there are more Add methods declared, you
 * may use mono_method_desc_search_in_class (clazz, ":Add(T)"),
 * you must substitute ":Add(T)" with the correct type, for example
 * for List, you would use ":Add(int)".
 */
method = mono_class_get_method_from_name (clazz, "Add", 1);
mono_runtime_invoke (method, obj, args, &exception);

Unfortunately this is not that helpful since it doesn't show a complete example, and no matter what I do (using mono_object_get_class or not) I end up with a warning followed by a crash when calling generic methods.

* Assertion: should not be reached at marshal.c:4315
SIGABRT stracktrace...

Below a sample C# class and C code calling into it. Invoking non-generic methods works just fine but I have no clue how to invoke generic methods. I'd appreciate any tips that could help.

Sample CSharp

namespace foo {
  class MainClass {
      public static void Main(string[] args) {
              Console.WriteLine("Main");
      }

      public void GenericMember(T t) {
             Console.WriteLine(t);
      }

      public static void GenericStatic(T t) {
             Console.WriteLine(t);
      }


      public void NonGenericMember(string t) {
             Console.WriteLine(t);
      }

      public static void NonGenericStatic(string t) {
            Console.WriteLine(t);
      } 
  }
}

Sample C

#include 
#include 
#include 
#include 
#include  
#include 
#include 
#include 
#include 

int main(int argc, char **argv) {
   mono_config_parse(NULL);

   MonoDomain *domain = mono_jit_init_version("app", "v4.0.30319");
   MonoAssembly *assembly = mono_domain_assembly_open(domain, "foo.exe");  
   MonoImage *image = mono_assembly_get_image(assembly);  

   mono_jit_exec(domain, assembly, argc, argv);

   MonoClass *klass = mono_class_from_name(image, "foo", "MainClass");
   MonoObject *instance = mono_object_new(domain, klass)

   MonoString *string = mono_string_new(domain, "hello");
   void *params[] = { string };

   //NonGenericStatic call (works)
   MonoMethod *method = mono_class_get_method_from_name(klass, "NonGenericStatic", 1);
   mono_runtime_invoke(method, NULL, params, NULL);

   //NonGenericMember call (works);
   method = mono_class_get_method_from(klass, "NonGenericMember", 1);
   mono_runtime_invoke(method, instance, params, NULL);

   //GenericStatic call (fails)
   method = mono_class_get_method_from_name(klass, "GenericStatic", 1);
   mono_runtime_invoke(method, NULL, params, NULL);

   //GenericMember call (fails)
   method = mono_class_get_method_from_name(klass, "GenericMember", 1);
   mono_runtime_invoke(method, instance, params, NULL);

   mono_jit_cleanup(domain, assembly);

   return 0;
}
c# c mono mono-embedding