Все начинается довольно просто.Маршаллер pinvoke сначала вызывает LoadLibrary и передает указанное имя DLL, свойство DllImportAttribute.Value.В вашем случае user32.dll уже загружен, потому что он загружается загрузчиком .NET, его счетчик ссылок просто увеличивается.Но обычно загрузчик Windows получает DLL, сопоставленную с адресным пространством процесса, чтобы можно было вызывать экспортированные функции.
Далее следует GetProcAddress, чтобы получить адрес вызываемой функции, свойство DllImportAttribute.EntryPoint.Маршаллер делает пару попыток, если вы не используете ExactSpelling.Имя функции типа "foo" проверяется несколькими возможными способами: foo и fooW или fooA.Неприятная деталь реализации Win32 связана с различием между символами Unicode и Ansi.Здесь имеет значение свойство CharSet.
Теперь мне нужно немного помахать руками, потому что это сложно.Маршаллер создает кадр стека, устанавливая аргументы, которые должны быть переданы в экспортируемую функцию.Для этого требуется код низкого уровня, тщательно исключенный из посторонних глаз.Принимайте во внимание, что он выполняет тот тип переводов, который поддерживает класс Marshal для преобразования между управляемым и неуправляемым типами.Здесь имеет значение свойство DllImportAttribute.CallingConvention, поскольку оно определяет, какое значение аргумента должно быть размещено там, чтобы вызываемая функция могла правильно его прочитать.
Затем он устанавливает обработчик исключений SEH, чтобы аппаратные исключения, вызванные вызываемым кодом, могли быть перехвачены и преобразованы в управляемое исключение.Тот, который генерирует более распространенный, AccessViolationException.И другие.
Затем он помещает специальный стек в стек, чтобы указать, что неуправляемый код собирается начать использовать стек.Это предотвращает грубую сборку мусора в кадрах неуправляемого стека и интерпретирует указатели, которые он там находит, как ссылки на управляемые объекты.Вы можете увидеть этот файл cookie в стеке вызовов отладчика [Managed to Native Transition].
Далее, просто косвенный вызов адреса функции, найденный с помощью GetProcAddress ().При этом запускается неуправляемый код.
После вызова может потребоваться очистка для освобождения памяти, выделенной для передачи неуправляемых аргументов.Возвращаемое значение может потребоваться преобразовать обратно в управляемое значение.И все, при условии, что ничего неприятного не произошло, выполнение продолжается при следующей инструкции управляемого кода.