什么是(fnptr)*类型以及如何创建呢? [英] What is the (fnptr)* type and how to create it?
问题描述
下面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);
型舍入类型= typeof运算(型).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屋!