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

时间:2012-02-28 23:18:51

标签: .net dllimport internals

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

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

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

3 个答案:

答案 0 :(得分:35)

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

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

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

答案 1 :(得分:15)

这是一个老线程。因为CoreCLR现在是在GitHub上开源的;如果有人仍在寻求答案,那么这是official documentation

  

Calling from managed to native code

     

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

     

有一个名为HCall(用于Helper调用)的FCall的小变体,用于实现JIT助手,用于访问多维数组元素,范围检查等.HCall和FCall之间的唯一区别是赢得了HCall方法不会出现在异常堆栈跟踪中。

然后它继续在副标题中出现:

以示例:

答案 2 :(得分: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函数。关于编组如何在这个地方工作的文章并不是很清楚,但总的来说,这显然取决于运行时实现,因为它既a)声明函数体[取决于编组格式]又b)执行任何所需的编组