Российский Государственный Технологический Университет им. К.Э. Циолковского
Опубликован: 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 возможны следующие причины:

  • чтобы избежать использования имен API-функций, чувствительных к регистру знаков;
  • чтобы привести имена в соответствие с существующими стандартами именования;
  • чтобы сделать возможным вызов функций, принимающих данные разных типов (объявляя несколько версий одной и той же функции DLL);
  • чтобы упростить применение API-интерфейсов, которые содержат функции версий для ANSI и Unicode.

Переименование функции в C#

Для задания функции DLL по имени или порядковому номеру можно использовать поле DllImportAttribute.EntryPoint. Если имя функции в определении метода совпадает с именем точки входа в DLL, явно задавать функцию с помощью поля EntryPoint не требуется. В противном случае, чтобы указать имя или порядковый номер, следует использовать одну из следующих форм атрибута:

[DllImport("dllname", EntryPoint="Functionname")]
 [DllImport("dllname", EntryPoint="#123")]

При этом порядковому номеру должен предшествовать знак ' # '.

Ниже приводится пример переименования функции. Имя функции MessageBoxA заменяется на MsgBox с помощью поля EntryPoint. Неуправляемая функция MessageBoxA, которая является точкой входа, в управляемом коде представляется под именем MsgBox:

using System.Runtime.InteropServices;

public class Win32
 {
     [DllImport("user32.dll", EntryPoint="MessageBoxA")]
     public static extern int MsgBox(int hWnd,
                String text,
                String caption,
                uint type);
 }

Указание набора знаков

Поле DllImportAttribute.CharSet играет двойную роль:

  • управляет маршалингом строк;
  • определяет порядок нахождения платформным вызовом имен функций в DLL.

Некоторые API экспортируют две версии функций, которые принимают строковые аргументы: узкую (ANSI) и широкую (Unicode). Например, Win32 API для функции MessageBox содержит следующие имена точек входа:

  • MessageBoxA — обеспечивает форматирование с использованием 1-байтовых символов ANSI, на что указывает буква " A ", добавляемая в конец имени точки входа. При вызовах MessageBoxA маршалинг строк всегда выполняется в формате ANSI, который обычно применяется на платформах Windows 98 и Windows 95;
  • MessageBoxW — обеспечивает форматирование с использованием 2-байтовых символов Unicode, на что указывает буква " W ", добавляемая в конец имени точки входа. При вызовах MessageBoxW маршалинг строк всегда выполняется в формате Unicode, который обычно применяется на платформах Windows NT, Windows 2000 и Windows XP.

Маршалинг строк и совпадение имен

Поле CharSet может принимать следующие значения:

  • CharSet.Ansi (стандартное значение).

    При этом:

    1. Платформный вызов выполняет маршалинг строк из их управляемого формата Unicode в формат ANSI.
    2. Если значение поля DllImportAttribute.ExactSpelling оказывается установленным в true, как это принято по умолчанию в Visual Basic .NET, платформный вызов ищет только указанное имя. Например, если указано MessageBox, платформный вызов ищет именно MessageBox. Если он не может найти точное посимвольное совпадение, возникает исключение при выполнении вызова функции.

    Когда значение поля ExactSpelling установлено в false, как это принято по умолчанию в C# и управляемых расширениях для C++, платформный вызов сначала ищет точный псевдоним ( MessageBox ), а затем добавленное имя ( MessageBoxA ), если точный псевдоним не найден.

    Следует учитывать, что механизм совпадения имен в формате ANSI отличается от механизма совпадения имен в формате Unicode.

  • CharSet.Unicode.

    При этом платформный вызов обеспечивает маршалинг строк путем копирования строки из их управляемого формата в формат Unicode.

    Если же при этом значение поля ExactSpelling оказывается равным true, действует принцип совпадения имен: платформный вызов ищет только указанное имя. Например, если указано MessageBox, платформный вызов ищет именно MessageBox. Если он не может найти точное посимвольное совпадение, возникает сбой.

    А если значение поля ExactSpelling устанавливается в false, как это принято по умолчанию в C#, платформный вызов сначала ищет добавленное имя ( MessageBoxW ), а затем – точный псевдоним ( MessageBox ), если добавленное имя не найдено.

  • CharSet.Auto.

    При этом платформный вызов выбирает между форматами ANSI и Unicode во время выполнения в соответствии с платформой назначения.

< Лекция 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