下面的IL代码创建一个名为(fnptr)*
的Type示例(标记0x 2000000-无效,模块mscorlib.dll)。
ldtoken method void* ()*
call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
此类型的用途是什么?是否可以在C#中创建此类型示例而无需编写任何IL代码,或者使用反射?* 标记上的Module.ResolveType* 引发 ArgumentOutOfRangeException。
编辑:
很明显,(fnptr)
类型是IL方法指针类型的内部CLR类型表示,尽管在删除最后一个*
时,它只返回IntPtr
。
编辑2:(fnptr)
来自SSCLItypestring.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)");
}
为什么基本的fnptr返回IntPtr可以在 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;
}
}
}
看来他们忘了修了。
4条答案
按热度按时间xqkwcwgp1#
我真实的的不知道你在问什么,为什么你认为有什么不对。(fnptr)* 是指向非托管函数指针的指针的类型名。它在CLR中得到特殊处理确实很奇怪,我怀疑它是考古学上的产物。可以追溯到.NET和委托发明之前的时间。CLR在Project 42中作为“通用运行时”开始存在,一个失败的项目。
也许一些C++/CLI代码来演示如何生成一个是有用的,向您展示了如何创建它:
输出:
(fnptr)*
unftdfkk2#
不知道你在哪里看到FNPTR被宣布。
对于此代码:
ILASM(4.5.22.0)输出以下内容:
更新#1:
也许我在这里是密集的,但我没有看到FNPTR是从这个代码生成的:
IL如下所示:
Type.ToString()
调用是自ToString() is a virtual method以来的callvirt
操作。虚函数通常表现为函数指针的结构体,我想,这会导致发出FNPTR。如果你在
()*
中省略*
,导致()
,你现在描述的是一个函数,而不是函数指针。当您看到FNPTR时,您使用的是什么版本的.NET?您使用什么来提取IL?
hsgswve43#
可以将 * 指针的签名加载到 * 函数指针:
6是字段,15是指针,27是函数指针,0,0,1是没有返回或参数的方法签名。
ckx4rj1h4#
在C# 9的上下文中应答函数指针现在可以通过
delegate*
语法直接表示和使用。但是,运行时(.NET 7)仍然有7年前的限制: