Incrustación mono, llame a un método genérico C#de C
mono-embedding (1)
No puede invocar métodos genéricos de esa manera y, lamentablemente, la documentación es un poco engañosa. Si desea invocar public void GenericMember<T>(T t)
con un parámetro String
, debe encontrar el método con la firma public void GenericMember<String>(String t)
y usar mono_runtime_invoke
en él.
La forma más sencilla de hacerlo es utilizar el método MethodInfo.MakeGenericMethod a través de un método de utilidad C #:
public static IntPtr Utility(MethodInfo method, Type type)
{
return method.MakeGenericMethod(type).MethodHandle.Value;
}
Usando la API Mono integrada, encuentre el método de Utility
, MonoMethod*
con el MonoMethod*
representa el GenericMethod<T>(T t)
y el tipo que desea (String en su ejemplo). El retorno de esta invocación será un MonoMethod*
que representará GenericMethod<String>(String t)
. Este es el método que necesita invocar.
Hice una publicación detallada con el código fuente aquí .
Tengo problemas para averiguar cómo llamar al método genérico (tanto estático como no estático) de C.
El principal culpable es que llamar a los métodos genéricos es esencialmente indocumentado, no hay ejemplos en el repositorio mono pero hay una mención de que esto es supuestamente posible en los documentos:
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<int>, you would use ":Add(int)".
*/
method = mono_class_get_method_from_name (clazz, "Add", 1);
mono_runtime_invoke (method, obj, args, &exception);
Lamentablemente, esto no es tan útil, ya que no muestra un ejemplo completo, y no importa lo que hago (utilizando mono_object_get_class
o no) termino con una advertencia seguida de un bloqueo al llamar a métodos genéricos.
* Assertion: should not be reached at marshal.c:4315
SIGABRT stracktrace...
Debajo de una muestra de clase de C # y un código de C para invocarlo. Invocar métodos no genéricos funciona bien, pero no tengo idea de cómo invocar métodos genéricos. Agradecería cualquier consejo que pueda ayudar.
Ejemplo CSharp
namespace foo {
class MainClass {
public static void Main(string[] args) {
Console.WriteLine("Main");
}
public void GenericMember<T>(T t) {
Console.WriteLine(t);
}
public static void GenericStatic<T>(T t) {
Console.WriteLine(t);
}
public void NonGenericMember(string t) {
Console.WriteLine(t);
}
public static void NonGenericStatic(string t) {
Console.WriteLine(t);
}
}
}
Muestra C
#include <mono/jit/jit.h>
#include <mono/metadata/mono-config.h>
#include <mono/metadata/metadata.h>
#include <mono/metadata/appdomain.h>
#include <mono/metadata/class.h>
#include <mono/metadata/assembly.h>
#include <mono/metadata/image.h>
#include <mono/metadata/object.h>
#include <mono/metadata/debug-helpers.h>
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;
}