Совмещение управляемого и неуправляемого кодов
Идентификация вызываемой функции
Идентификация функции DLL предполагает:
- указание имени вызываемой функции;
- указание имени содержащей ее библиотеки DLL (имени файла).
Например, идентификация функции MessageBox включает имя ( MessageBox ) и имя файла (User32.dll, User32, или user32). Программный интерфейс приложений Microsoft Windows (Win32 API) может содержать несколько версий функции. Например, версии функций, которые работают с символами и строками: для 1-байтовых символов – ANSI и для 2-байтовых символов – Unicode.
Так MessageBoxA является точкой входа для функции MessageBox версии ANSI, а MessageBoxW — точкой входа для аналогичной функции версии Unicode.
Имена функций, располагаемых в определенной библиотеке DLL, например, user32.dll, можно получить с помощью ряда инструментов в режиме командной строки. Например, для получения имен функций можно использовать вызовы
dumpbin –exports user32.dll
или
link –dump –exports user32.dll.
Создание класса для размещения библиотечной функции
Эта деятельность называется упаковкой неуправляемой функции в обертку управляемого класса.
На самом деле неуправляемые функции можно и не обертывать. Но это удобно, поскольку процесс определения функций DLL может быть трудоемким и представлять собой источник ошибок.
Для обертывания можно использовать существующий класс, можно создать отдельный класс для каждой неуправляемой функции либо создать один класс для всего набора используемых в приложении неуправляемых функций. В классе-обертке для каждой вызываемой библиотечной функции должен быть определен собственный статический метод. Это определение может включать дополнительную информацию, например характеристику символьного набора или информацию о соглашении о вызовах, которое используется при передаче параметров функции. Если эта информация отсутствует, используются соглашения, принятые по умолчанию.
После упаковки функции в обертку ее методы можно вызывать точно так же, как и методы любой другой статической функции. Платформный вызов обеспечивает передачу управления библиотечной функции автоматически.
Прототипы в управляемом коде
Для обращения к неуправляемой функции DLL из управляемого программного кода требуется знать имя функции и имя библиотеки DLL, которая ее экспортирует.
Располагая этой информацией, можно начинать создавать управляемое определение для неуправляемой функции, реализованной в DLL.
При этом с помощью атрибутов можно управлять порядком создания, платформным вызовом функции и маршалингом данных в функцию и из нее (передачу значений параметров и получение возвращаемого значения):
using System.Runtime.InteropServices; [DllImport("user32.dll")] public static extern int MessageBox(int hWnd, String text, String caption, uint type);
Поведение управляемого программного кода при его выполнении задается значениями полей атрибутов. Служба платформного вызова работает в соответствии с набором стандартных значений различных полей атрибутов, которые хранятся как метаданные в сборке.
В следующей таблице представлен полный набор полей атрибутов, имеющих отношение к платформному вызову. Для каждого поля в таблице имеется стандартное значение и ссылка на сведения относительно использования этих полей для определения неуправляемых функций DLL.
Управление службой платформного вызова сводится к применению полей атрибутов. Знание правил применения полей атрибутов – основа управления службой платформного вызова!