Российский Государственный Технологический Университет им. К.Э. Циолковского
Опубликован: 02.03.2007 | Доступ: свободный | Студентов: 5678 / 802 | Оценка: 3.96 / 3.45 | Длительность: 27:04:00
ISBN: 978-5-9556-0086-4
Лекция 14:

Совмещение управляемого и неуправляемого кодов

< Лекция 13 || Лекция 14: 12345 || Лекция 15 >

Идентификация вызываемой функции

Идентификация функции 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.

Управление службой платформного вызова сводится к применению полей атрибутов. Знание правил применения полей атрибутов – основа управления службой платформного вызова!

Поле Описание
BestFitMapping Отключает наилучшее соответствие
CallingConvention Задает соглашение о вызовах, которое должно использоваться при передаче аргументов методов. По умолчанию используется WinAPI, что соответствует __ stdcall для 32-разрядных платформ на основе процессора Intel
CharSet Управляет передачей имен и задает способ маршалинга строковых аргументов в функцию. Стандартное значение — CharSet.Ansi
EntryPoint Задает точку входа DLL для вызова
ExactSpelling Указывает, должна ли быть изменена точка входа в соответствии с символьным набором. Стандартное значение варьируется в зависимости от языка программирования
PreserveSig Указывает, должна ли управляемая подпись метода быть преобразована в неуправляемую подпись, которая возвращает значение HRESULT и для возвращаемого значения имеет дополнительный аргумент [out, retval].

По умолчанию используется значение true (подпись не должна преобразовываться)

SetLastError Позволяет вызывающему объекту для определения факта ошибки при выполнении метода использовать API-функцию Marshal.GetLastWin32 Error. В Visual Basic по умолчанию используется значение true; в C# и C++ — значение false
ThrowOnUnmappableChar Управляет возникновением исключения при появлении несопоставимого символа Unicode, который преобразуется в символ ANSI " ?"
< Лекция 13 || Лекция 14: 12345 || Лекция 15 >
kewezok kewezok
kewezok kewezok
Елена Шляхт
Елена Шляхт
Объясните плиз в чем отличие а++ от ++а
Почему результат разный?
int a=0, b=0;
Console.WriteLine(a++); //0
Console.WriteLine(++b); //1
a++;
++b;
Console.WriteLine(a); //2
Console.WriteLine(b); //2