gpt4 book ai didi

mono - 使用 Mono 嵌入获取泛型类型

转载 作者:行者123 更新时间:2023-12-04 15:59:05 34 4
gpt4 key购买 nike

如何使用单声道嵌入调用创建通用 List 对象?我可以得到 List 的 MonoClass:

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]");

但没有运气。

更新:

好的,我找到了方法。我仍然想看看是否有官方的做事方式,因为这个 hack 对我来说太脏了。

基本上我搜索了泛型方法的单声道来源并找到了 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* - 虽然它就像从结构中获取 -> 类型一样容易 - 这是内部的并且通过函数访问它是内部的。 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 的静态链接,但这是一个更糟糕的黑客。并且 mono_class_inflate_generic_type 被标记为 DEPRECATED - 所以,如果这被弃用,那么 其中是现代的吗?

最佳答案

在许多情况下,可以使用托管帮助程序方法解决单声道嵌入难题。这是这里使用的方法。

所以我们有:

  • 接受泛型类型定义和泛型参数类型数组的托管帮助器方法。
  • 接受泛型类型定义名称(例如:System.Collections.Generic.List`1)、包含类型(或使用程序集限定名称)和所需泛型参数类型的对象的程序集镜像的客户端方法。我们检索对象的底层 monoType。

  • 请注意,将类型信息传递到托管层时,它必须是从 mono_type_get_object() 获得的 MonoReflectionType 实例。

    托管助手方法很简单,它会执行实际的实例化:
        public static object CreateInstanceOfGenericType(Type genericTypeDefinition, Type[] parms)
    {
    // construct type from definition
    Type constructedType = genericTypeDefinition.MakeGenericType(parms);

    // create instance of constructed type
    object obj = Activator.CreateInstance(constructedType);

    return obj;
    }

    在这种情况下,从 Objective-C 调用帮助程序代码:
    + (id)createInstanceOfGenericTypeDefinition:(char *)genericTypeDefinitionName monoImage:(MonoImage *)monoImage itemObject:(id)itemObject
    {
    // get the contained item monoType
    MonoType *monoType = [DBType monoTypeForMonoObject:[itemObject monoObject]];
    MonoReflectionType *monoReflectionType = mono_type_get_object([DBManagedEnvironment currentDomain], monoType);

    // build a System.Array of item types
    DBManagedObject *argType = [[DBManagedObject alloc] initWithMonoObject:(MonoObject *)monoReflectionType];
    NSArray *argTypes = @[argType];
    DBSystem_Array *dbsAargTypes = [argTypes dbsArrayWithTypeName:@"System.Type"];

    // get the generic type definition
    //
    // Retrieves a MonoType from given name. If the name is not fully qualified,
    // it defaults to get the type from the image or, if image is NULL or loading
    // from it fails, uses corlib.
    // This is the embedded equivalent of System.Type.GetType();
    MonoType *monoGenericTypeDefinition = mono_reflection_type_from_name(genericTypeDefinitionName, monoImage);

    // create instance using helper method
    MonoMethod *helperMethod = [DBManagedEnvironment dubrovnikMonoMethodWithName:"CreateInstanceOfGenericType" className:"Dubrovnik.FrameworkHelper.GenericHelper" argCount:2];
    void *hargs [2];
    hargs[0] = mono_type_get_object([DBManagedEnvironment currentDomain], monoGenericTypeDefinition);
    hargs[1] = [dbsAargTypes monoArray]; // a monoArray *

    MonoObject *monoException = NULL;
    MonoObject *monoObject = mono_runtime_invoke(helperMethod, NULL, hargs, &monoException);
    if (monoException) NSRaiseExceptionFromMonoException(monoException);

    id object = [System_Object subclassObjectWithMonoObject:monoObject];

    return object;
    }

    完整代码见 Dubrovnik在 Github 上

    关于mono - 使用 Mono 嵌入获取泛型类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17628411/

    34 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com