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