Что такое [DllImport ("QCall")]?

многие методы в библиотеке .Net реализованы в собственном коде. Те, которые исходят из самой структуры, отмечены [MethodImpl(MethodImplOptions.InternalCall)]. Те, которые приходят из какой-то неуправляемой DLL, помечены [DllImport] (например,[DllImport("kernel32.dll")]). Пока ничего необычного.

но во время написания ответ на другой вопрос, я обнаружил, что есть много методов, отмеченных [DllImport("QCall")]. Они кажутся внутренней реализацией .Net (например,GC._Collect()).

мой вопрос: что именно [DllImport("QCall")] В смысле? В чем разница между [DllImport("QCall")] и [MethodImpl(MethodImplOptions.InternalCall)]?

3 ответов


Это старая нить. Поскольку CoreCLR теперь открыт для GitHub; если кто-то все еще ищет ответ, вот официальная документация:

звонок из управляемого в машинный код

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

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

и затем он продолжается в подзаголовках:

примеры:


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

QCalls-это вызовы собственных методов в среде CLR. Они ведут себя как другие [DllImport]s, но они быстрее, потому что они делают конкретные (недокументированные) предположения о том, что делают собственные методы, поэтому они могут пропустить различные маршалинга и проверки GC и исключений.

InternalCall другое; это требует особого осмысления вещей, которые генерируются во время выполнения (это не очень четкий.)


дополнение @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) делает любой необходимый маршалинг.