什么是(fnptr)*类型以及如何创建呢? [英] What is the (fnptr)* type and how to create it?

查看:344
本文介绍了什么是(fnptr)*类型以及如何创建呢?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面IL code创建了一个名为类型实例(fnptr)* 。(令牌0x2000000 - 无效,模块mscorlib.dll中)

  ldtoken方法无效*()*
调用类[mscorlib程序]的System.Type [mscorlib程序]的System.Type :: GetTypeFromHandle(值类型[mscorlib程序] System.RuntimeTypeHandle)
 

这是什么类型的目的是什么?是否有可能建立在C#这种类型的实例,而无需编写任何IL code,也许与反思? Module.ResolveType 的令牌上抛出的 ArgumentOutOfRangeException 的。

编辑:

很明显的(fnptr)类型是IL方法指针类型的内部CLR类型重新presentation,虽然去掉最后 * ,它只是返回的IntPtr

编辑#2:

(fnptr)来自可在的 SSCLI typestring.cpp 的:

  // ...或函数指针
否则,如果(ty.IsFnPtrType())
{
    //不要试图目前格式化这一点,就可能会触发GC由于修正。
    tnb.AddName(L(fnptr));
}
 

为什么基本fnptr返回的IntPtr中可以看到的 typehandle.cpp 的:

  OBJECTREF类型句柄:: GetManagedClassObject()const的
{
 

     

[...]

 开关(GetInternalCorElementType()){
        案例ELEMENT_TYPE_ARRAY:
        案例ELEMENT_TYPE_SZARRAY:
        案例ELEMENT_TYPE_BYREF:
        案例ELEMENT_TYPE_PTR:
            返回((ParamTypeDesc *)AsTypeDesc()) - > GetManagedClassObject();

        案例ELEMENT_TYPE_VAR:
        案例ELEMENT_TYPE_MVAR:
            返回((TypeVarTypeDesc *)AsTypeDesc()) - > GetManagedClassObject();

            //此版本的函数指针被映射到一个IntPtr。此结果在信息丢失。修复下一个版本
        案例ELEMENT_TYPE_FNPTR:
            返回TheIntPtrClass() - > GetManagedClassObject();

        默认:
        _ASSERTE(坏分子类型!);
        返回NULL;
        }
    }
}
 

所以看起来他们已经忘记修复它。

解决方案

这是可能加载函数指针的签名:

 公共静态不安全类型GetTypeFromFieldSignature(byte []的签名,类型declaringType = NULL)
{
    declaringType = declaringType? typeof运算(对象);
    类型sigtype = typeof运算(型).Module.GetType(System.Signature);
    型舍入类型= ty​​peof运算(型).Module.GetType(System.RuntimeType);
    VAR男星= sigtype.GetConstructor(BindingFlags.Public | BindingFlags.Instance,空,新的[] {typeof运算(无效*)的typeof(INT),舍入类型},NULL);
    固定(BYTE * PTR =签名)
    {
        对象sigobj = ctor.Invoke(新对象[] {(IntPtr的)PTR,signature.Length,declaringType});
        返程(类型)sigtype.InvokeMember(的FieldType,BindingFlags.NonPublic可| BindingFlags.Instance | BindingFlags.GetProperty,空,sigobj,NULL);
    }
}

变种fnptrPtr = GetTypeFromFieldSignature(新字节[] {6,15,27,0,0,1});
 

6场,15个为指针,27是函数指针,0,0,1是没有回报或参数的方法签名。

The following IL code creates a Type instance named (fnptr)* (token 0x2000000 - invalid, module mscorlib.dll).

ldtoken method void* ()*
call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)

What's the purpose of this type? Is it possible to create this type instance in C# without writing any IL code, maybe with reflection? Module.ResolveType on the token throws ArgumentOutOfRangeException.

Edit:

It's clear the (fnptr) type is an internal CLR type representation of an IL method pointer type, though when removing the last *, it simply returns IntPtr.

Edit #2:

The (fnptr) comes from a function that can be seen in the SSCLI typestring.cpp:

// ...or function pointer
else if (ty.IsFnPtrType())
{
    // Don't attempt to format this currently, it may trigger GC due to fixups.
    tnb.AddName(L"(fnptr)");
}

Why basic fnptr returns IntPtr can be seen in typehandle.cpp:

OBJECTREF TypeHandle::GetManagedClassObject() const
{

[...]

        switch(GetInternalCorElementType()) {
        case ELEMENT_TYPE_ARRAY:
        case ELEMENT_TYPE_SZARRAY:
        case ELEMENT_TYPE_BYREF:
        case ELEMENT_TYPE_PTR:
            return ((ParamTypeDesc*)AsTypeDesc())->GetManagedClassObject();

        case ELEMENT_TYPE_VAR:
        case ELEMENT_TYPE_MVAR:
            return ((TypeVarTypeDesc*)AsTypeDesc())->GetManagedClassObject();

            // for this release a function pointer is mapped into an IntPtr. This result in a loss of information. Fix next release
        case ELEMENT_TYPE_FNPTR:
            return TheIntPtrClass()->GetManagedClassObject();

        default:
        _ASSERTE(!"Bad Element Type");
        return NULL;
        }
    }
}

So it looks they've forgotten to fix it.

解决方案

It is possible to load the signature of a function pointer:

public static unsafe Type GetTypeFromFieldSignature(byte[] signature, Type declaringType = null)
{
    declaringType = declaringType ?? typeof(object);
    Type sigtype = typeof(Type).Module.GetType("System.Signature");
    Type rtype = typeof(Type).Module.GetType("System.RuntimeType");
    var ctor = sigtype.GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, new[]{typeof(void*), typeof(int), rtype}, null);
    fixed(byte* ptr = signature)
    {
        object sigobj = ctor.Invoke(new object[]{(IntPtr)ptr, signature.Length, declaringType});
        return (Type)sigtype.InvokeMember("FieldType", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetProperty, null, sigobj, null);
    }
}

var fnptrPtr = GetTypeFromFieldSignature(new byte[]{6, 15, 27, 0, 0, 1});

6 is field, 15 is pointer, 27 is function pointer and 0, 0, 1 is a method signature without return or parameters.

这篇关于什么是(fnptr)*类型以及如何创建呢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆