Информационный сайт

 

Реклама
bulletinsite.net -> Книги на сайте -> Программисту -> Троелсен Э. -> "С# и платформа .NET. Библиотека программиста" -> 229

С# и платформа .NET. Библиотека программиста - Троелсен Э.

Троелсен Э. С# и платформа .NET. Библиотека программиста — СПб.: Питер, 2004. — 796 c.
ISBN 5-318-00750-3
Скачать (прямая ссылка): cplatforma2004.pdf
Предыдущая << 1 .. 223 224 225 226 227 228 < 229 > 230 231 232 233 234 235 .. 320 >> Следующая

Таким образом, при значении se поля i ng часть работы по розыску
нужной функции службы PInvoke берут на себя. Например, в нашей ситуации суффикс А будет автоматически добавлен при работе в среде ANSI, а суффикс W - при работе в среде Unicode.
Поле CharSet
Чтобы явно указать кодировку для символьных данных при вызове внешней фуь к-ции из кода традиционного модуля DLL, мы должны задать значение в поле
568 Глава 12 • Взаимодействие с унаследованным программным кодом
типа Dl 1 ipnport Attribute. Для этого поля используются значения из перечисления
CharSet, представленные в табл. \?..3
Таблица 12.3. Значения перечисления CharSet
Значение Описание
Ansi Определяет, что строковые значения должны быть переданы в однобайтовой
кодировке ANSI
Auto Определяет, что службы Plnvoke сами должны определить, как передавать
строковые значения (Unicode в WinNT/Win2000 и ANSI в Win 9х)
None Это значение применяется по умолчанию. Оно значит, что не определена
используемая кодировка и среда выполнения должна сделать это автоматически
Unicode Определяет, что строковые значения должны передаваться в двухбайтовой
кодировке Unicode
Чтобы принудительно передавать все строковые значения как Unicode (и подвергнуть свое приложение риску неправильной работы в Wm95/98/MIi), можно использовать такой код:
// Принудительно используем точное иия и кодировку Unicode [DnImportruser32". ExactSpelling - true. CharSet=CharSet.Unicode)] public static extern int MessageBoxW(...):
В большинстве случаев гораздо удобнее и безопаснее задать для поля CharSet значение CharSet.Auto или просто оставить значение по умолчанию (None). В этой ситуации код будет корректно выполняться на разных платформах и, таким образом, станет более переносимым.
Поля CallingConvention и EntryPoint
Последние два поля Dil ImportAttnbute, которые мы рассмотрим, — это поля CaI -lingConventionnEntryPoint. Каквы, наверное, знаете, для функций Win32 API можно использовать множество специальных параметров (typedef), которые определяют то, каким образом параметры будут переданы функции: объявление С (С declaration), быстрый вызов, стандартный вызов и т. п. Эти значения для вызова через PInvoke можно определить с помощью поля CallingConvention, для которого используются значения из одноименного перечисления. В этом перечислении предусмотрены такие значения, как Cdecl, Wi парі, StdCal 1 и т. п. По умолчанию используется значение StdCal 1, и, как правило, в большинстве ситуаций этого вполне достаточно (поскольку это соответствует наиболее распространенному соглашению о вызовах, используемому в Win32).
Последнее поле (по порядку рассмотрения, но не по важности) — это поле EntryPoint. По умолчанию значение этого поля совпадает с именем функции-прототипа в С#. Таким образом, в нашем примере значение этого поля будет автоматически установлено в MessageBoxW:
// Значение поля EntryPoint будет автоматически установлено в 'MessageBoxW'
[011 Importe"user32". ExactSpelling - true. CharSet-CharSet.Unicode)] public static extern int MessageBoxW..,):
Однако не всегда в коде можно использовать то же имя, которое нужно использовать для вызова функции из внешней традиционной библиотеки DLL
Взаимодействие .NET и COM 569
(самая простая ситуация — функция с тем же названием уже определена в коде .NET). В этой ситуации мы можем явно указать имя вызываемой внешней функции в качестве значения поля Entry Po int:
public class PInvokeClient 1
II Функция .NET DisplayMessageO будет вызывать функцию MessageBoxO
// из традиционной DLL
[DilImport!"user32". ExactSpelling - true. CharSet-CharSet. Unicode, EntryPoint ¦
"MessageBoxW")]
public static extern int DisplayMessageCint hWnd. String pText. String pCaption.
int uType);
public static int MainfstringCl args) {
String pText - "Hello World!"; String pCaption = "PInvoke Test";
// Реально будет вызвана функция MessageBoxO D1splayHessage<0. pText. pCaption. 0); return 0;
I
}
Код приложения PinvokeExample можно найти подкаталоге Chapter 12.
Взаимодействие и СОМ
Следующий тип взаимодействия с унаследованным кодом, который мы должны рассмотреть, — это взаимодействие с модулями СОМ. Очень часто при создании приложений .NET оказывается, что им приходится взаимодействовать с существующими СОМ-серверами. Естественно, для решения этой задачи необходимо обеспечить какой-то промежуточный уровень, который транслировал бы вызовы .NET в вызовы СОМ (представляя типы СОМ в виде типов .NET). В идеальной ситуации процесс подобного преобразования должен быть совершенно прозрачен для типов .NET, чтобы они могли обращаться к типам СОМ точно так же, как и к дру -гим типам .NET.
Роль подобного промежуточного уровня в .NETвыполняют службы RCW(Run-time Callable Wrapper, вызываемая оболочка времени выполнения). Каждому классу СОМ (соклассу), к которому производятся вызовы из клиента .NET, необходима своя оболочка - свой RCW. Таким образом, если мы работаем с одним приложением ,NET, которое обращается к трем соклассам СОМ, нам потребуются три отдельных RCW, которые будут преобразовывать вызовы .NETb вызовы СОМ. Общая схема этого процесса представлена на рис. 12.1.
Предыдущая << 1 .. 223 224 225 226 227 228 < 229 > 230 231 232 233 234 235 .. 320 >> Следующая
Реклама
Авторские права © 2009 AdsNet. Все права защищены.
Rambler's Top100