【发布时间】:2013-07-11 19:01:44
【问题描述】:
如何使用单声道嵌入式调用创建通用 List
MonoClass* list = mono_class_from_name(mscorlibimage,
"System.Collections.Generic", "List`1");
我在文档中看到有
mono_class_from_generic_parameter(MonoGenericParam*...)
但我不知道在哪里以及如何获得 MonoGenericParam。或者也许我需要为 mono_class_from_name 构建一个有效的名称?我认为这可能会慢一些,但我现在会接受。我试过了
MonoClass* list = mono_class_from_name(mscorlib::get().image, "System.Collections.Generic", "List`1[System.String]");
但没有运气。
更新:
好的,我找到了方法。不过我还是想看看是否有官方的做事方式,因为这个黑客对我来说看起来太脏了。
基本上,我在 mono 源代码中搜索了泛型方法并找到了 mono_class_bind_generic_parameters(参见 https://raw.github.com/mono/mono/master/mono/metadata/reflection.c)。除了 .so 之外,我还必须链接到 libmono-2.0.a 才能使用它。但它奏效了:
extern "C" MonoClass*
mono_class_bind_generic_parameters(MonoClass *klass,
int type_argc, MonoType **types, bool is_dynamic);
MonoClass* list = mono_class_from_name(mscorlib::get().image,
"System.Collections.Generic", "List`1");
MonoClass* strcls = mono_class_from_name(mscorlib::get().image, "System", "String");
printf("str class: %p\n", strcls);
MonoType* strtype = mono_class_get_type(strcls);
printf("str type: %p\n", strtype);
MonoType* types[1];
types[0] = strtype;
list = mono_class_bind_generic_parameters(list, 1, types, false);
printf("list[string] class: %p\n", list);
MonoObject* obj = mono_object_new(domain, list);
printf("list[string] created: %p\n", obj);
我想我可以获取这些方法的来源(更新:几乎没有)并重新实现它们(它们解析元数据等)——如果我不想链接到 .a——但我想知道是否有更简单的方法。 Mono 文档不像他们过去那样回答任何问题。
更新:找到这个线程:http://mono.1490590.n4.nabble.com/Embedded-API-Method-signature-not-found-with-generic-parameter-td4660157.html 这似乎是说不存在我想要的嵌入式 API(即他们不费心公开 mono_class_bind_generic_parameters)。有人可以证明它是正确的吗?顺便说一句,使用这种方法,我得到 MonoReflectionType* 并且无法从中取回 MonoType* - 虽然从结构中获取 ->type 一样容易 - 这是内部的,通过函数访问它是内部的。 Mono Embedded 应改为“Mono Internal”。
更新:另一种方法是使用内部结构的副本破解 mono_class_inflate_generic_type:
struct _MonoGenericInst {
uint32_t id; /* unique ID for debugging */
uint32_t type_argc : 22; /* number of type arguments */
uint32_t is_open : 1; /* if this is an open type */
MonoType *type_argv [1];
};
struct _MonoGenericContext {
/* The instantiation corresponding to the class generic parameters */
MonoGenericInst *class_inst;
/* The instantiation corresponding to the method generic parameters */
void *method_inst;
};
_MonoGenericInst clsctx;
clsctx.type_argc = 1;
clsctx.is_open = 0;
clsctx.type_argv[0] = mono_class_get_type(System::String::_SClass());
MonoGenericContext ctx;
ctx.method_inst = 0;
ctx.class_inst = &clsctx;
MonoType* lt = mono_class_inflate_generic_type(
mono_class_get_type(System::Collections::Generic::List<System::String>::_SClass()),
&ctx);
这不需要到 .a 的静态链接,但更糟糕的是 hack。并且 mono_class_inflate_generic_type 被标记为已弃用 - 因此,如果已弃用,那么 哪个 是现代的?
【问题讨论】:
-
也许调用静态方法 Type.GetTypeFormTypeHandle 将 MonoType 转换为 MonoReflectionType 并在其上调用 MakeGenericType 实例方法并从结果 TypeHandle 属性中获取值,该属性应该是指向 MonoType 的指针。这些只是我实际上从未使用过 Mono Embedded 的猜测。
-
是的,在那个论坛中,我找到了一种涉及使用 TypeHandle IntPtr 并将其拆箱的方法。这是没有 hack 的最安全的方法,但是使用 C# 助手来创建嵌入式类型对我来说有点尴尬。
-
这是一个在 mono-devel 邮件列表 (lists.ximian.com/mailman/listinfo/mono-devel-list) 上提出的好问题
标签: mono mono-embedding