2012-02-28 2 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

+0

Я помню, как некоторое время читал, что «QCall» является частью clr.dll. Я, однако, не знаю много за этим. +1 за отличный вопрос. – ahawker

+11

Это особенность .NET 4. Вы можете получить немного информации из Справочного источника V4, посмотреть исходный код System.Runtime.CompilerServices.Jithelpers.cs. Строка появляется дважды в clr.dll, как __IsQCall и как встроенный литерал. Это сильно напоминает механизм расширения вне метода MethodImplOptions.InternalCall, доказывая, что это сложно без исходного кода CLR. –

ответ

14

Это старая резьба. Поскольку CoreCLR теперь открыт для GitHub; если кто-то до сих пор ищут ответ, вот official documentation:

Calling from managed to native code

У нас есть два метода для вызова в CLR из управляемого кода. FCall позволяет вам напрямую звонить в код CLR и обеспечивает большую гибкость с точки зрения манипулирования объектами, хотя легко вызвать GC-отверстия, не правильно отслеживая ссылки на объекты. QCall позволяет вам звонить в CLR через P/Invoke и намного сложнее случайно использовать, чем FCall. FCalls идентифицируются в управляемом коде как внешние методы с установленным битом MethodImplOptions.InternalCall. QCalls - это статические внешние методы, которые выглядят как обычные P/Invokes, но в библиотеку под названием «QCall».

Существует небольшой вариант FCall, называемый HCall (для вызова Helper) для реализации помощников JIT, для выполнения таких действий, как доступ к многомерным элементам массива, проверка диапазона и т. Д. Единственная разница между HCall и FCall заключается в том, что методы HCall не будет отображаться в трассе стека исключений.

А потом продолжается в подрубриками:

с примерами:

35

Я спросил некоторых людей в команде .Net об этом.

QCalls - это вызовы для собственных методов в среде CLR. Они ведут себя как другие [DllImport] s, но они быстрее, потому что они делают конкретные (недокументированные) предположения о том, что делают нативные методы, поэтому они могут пропустить различные сортировки и 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 функция. В статье не совсем понятно, как работает маршалинг в этом месте, но в целом это явно зависит от реализации времени выполнения, поскольку он и объявляет тело функции [которое зависит от формата маршалинга], и b) делает любое требуемое маршалинг ,

Смежные вопросы