什么是[DllImport(“ QCall”))?


71

.Net库中的许多方法都是用本机代码实现的。那些来自框架本身的标记为[MethodImpl(MethodImplOptions.InternalCall)]。来自非托管DLL的那些标记有[DllImport](例如[DllImport("kernel32.dll")])。到目前为止,没有任何异常。

但是在写另一个问题的答案时,我发现有很多用标记的方法[DllImport("QCall")]。它们似乎是.Net的内部实现(例如GC._Collect())。

我的问题是:究竟是什么[DllImport("QCall")]意思?[DllImport("QCall")]和之间有什么区别[MethodImpl(MethodImplOptions.InternalCall)]


1
这是一个特殊的内部通话;我正在尝试查找详细信息。
SLaks

我记得有一阵子,“ QCall”是clr.dll的一部分。但是,我对此并不了解。+1是一个很好的问题。
小贩

11
它是.NET 4的特定功能。您可以从V4参考源中获得一点点见识,查看System.Runtime.CompilerServices.Jithelpers.cs的源代码。该字符串在clr.dll中以__IsQCall和内联文字形式出现两次。这非常类似于MethodImplOptions.InternalCall之外的扩展机制,证明没有CLR源代码很难。
汉斯·帕桑

Answers:


19

这是一种旧思路。由于CoreCLR现在是在GitHub上开源的;如果仍然有人在寻找答案,这是官方文档

从托管代码到本机代码的调用

我们有两种从托管代码调用CLR的技术。FCall允许您直接调用CLR代码,并在处理对象方面提供了很大的灵活性,尽管通过不正确地跟踪对象引用很容易导致GC漏洞。QCall允许您通过P / Invoke调用CLR,与FCall相比,意外误用要难得多。FCall在托管代码中通过MethodImplOptions.InternalCall位置1来标识为外部方法。QCall是类似于常规P / Invokes的静态外部方法,但在名为“ QCall”的库中。

FCall有一个小的变体,称为HCall(用于Helper调用),用于实现JIT助手,用于执行诸如访问多维数组元素,范围检查等操作。HCall和FCall之间的唯一区别是HCall方法不会显示在异常堆栈跟踪中。

然后在子标题中继续:

带有示例:


36

我问了.Net团队中的一些人。

QCall是CLR运行时内对本机方法的调用。它们的行为与其他类似[DllImport],但是它们速度更快,因为它们对本机方法的作用做出了特定的(未记录的)假设,因此它们可以跳过各种编组,GC和异常检查。

InternalCall是不同的; 它用于调用在运行时生成的特殊反射样式的东西(这不是很清楚)。


0

在此处简要描述了补充@SLaks答案,MethodImplOptions.InternalCall:ThreadPoolPriority和MethodImplAttribute

基本上,InternalCall告诉运行时检查其自己的命名函数内部查找表。该表的存在是由于运行时代码中的源文件在编译运行时时显式声明了它们。它具有用于实现所有内部调用的函数指针的列表:

static ECFunc gGuidFuncs[] = { {FCFuncElement("CompleteGuid", NULL, (LPVOID)GuidNative::CompleteGuid)}, {NULL, NULL, NULL} };

该声明告诉运行时托管的Guid.CompleteGuid方法的方法主体实际上是本机C ++ GuidNative :: CompleteGuid函数。本文对于在此处如何进行封送处理不是很清楚,但是一般来说,这显然取决于运行时的实现,因为它a)声明了函数体[取决于封送格式]和b)进行了任何必需的封送处理。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.