2012-02-28 41 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功能。這篇文章並不是很清楚編組在這個地方是如何工作的,但是通常這顯然取決於運行時實現,因爲它既聲明瞭函數體[依賴於編組格式],又聲明瞭編組。