2012-02-28 273 views
61

.Net库中的许多方法都以本机代码实现。来自框架本身的标记为[MethodImpl(MethodImplOptions.InternalCall)]。那些来自某些非托管DLL的标记为[DllImport](例如[DllImport("kernel32.dll")])。迄今没有什么不寻常的什么是[DllImport(“QCall”)]?

但写answer for another question时,我发现有很多方法标记[DllImport("QCall")]。它们似乎是.Net的内部实现(例如GC._Collect())。

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

+1

这是一个特殊的内部调用;我试图找到细节。 – SLaks 2012-02-28 23:41:06

+0

我记得读过“QCall”是clr.dll的一部分。然而,我不知道那么多。 +1为一个优秀的问题。 – ahawker 2012-02-29 01:36:52

+11

这是一个.NET 4特有的功能。您可以从V4参考源中获得一些洞察,查看System.Runtime.CompilerServices.Jithelpers.cs的源代码。该字符串在clr.dll中出现两次,如__IsQCall和内联文字。这非常类似于MethodImplOptions.InternalCall之外的扩展机制,证明没有CLR源代码很困难。 – 2012-02-29 01:51:08

回答

14

这是一个旧线程。由于CoreCLR现在在GitHub上开源,如果有人仍然在寻求答案,这里是official documentation

Calling from managed to native code

我们有两种方法可以调用到托管代码的CLR。 FCall允许您直接调用CLR代码,并且在操作对象方面提供了很大的灵活性,但通过正确跟踪对象引用很容易导致GC漏洞。 QCall允许您通过P/Invoke调用CLR,并且比FCall更容易误用。 FCalls在托管代码中用MethodImplOptions.InternalCall位设置为extern方法。 QCalls是静态外部方法,看起来像普通的P/Invokes,但对于一个名为“QCall”的库。

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

然后继续在副标题:

举例:

35

我向.Net团队中的一些人询问了这个问题。

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

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

0

补充@SLaks答案,MethodImplOptions.InternalCall在这里简要描述:ThreadPoolPriority, and MethodImplAttribute

基本上,InternalCall通知运行时检查它自己的命名函数的内部查找表。该表存在是由于运行时代码中的源文件在编译运行时时显式声明它们。它有一个函数指针列表,实现所有内部呼叫:

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

这个声明告知运行时,对于管理Guid.CompleteGuid方法的方法体实际上是原生的C++ GuidNative :: CompleteGuid功能。这篇文章并不是很清楚编组在这个地方是如何工作的,但是通常这显然取决于运行时实现,因为它既声明了函数体[依赖于编组格式],又声明了编组。