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

 

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

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

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

Как мы уже говорили, одна из главных целей, которая преследовалась при создании библиотеки базовых классов .NET— спрятать от программиста низкоуровневые вызовы к Win32 API, Однако если нам все-таки потребовалось реализовать подобные вызовы — то PInvoke к нашим услугам. Кроме того, службы PInvoke могут быть использованы, конечно, и для доступа к функциям, определенным в пользе вательских модулях DLL. Таким образом, если в нашем распоряжении остались библиотеки унаследованного кода, написанного на С, при помощи PInvoke мы можем без каких-либо проблем к ним обращаться.
Проиллюстрируем это примером. Пример будет выглядеть как класс С#, из которого будет производиться вызов к функции Win32 API MessageBoxO. Вот он:
566 Глава 12 • Взаимодействие с унаследованным программным кодом
namespace PlnvokeEx?uiple {
using System;
Il Нужно для получения доступа к типан PInvoke
using System. Runti me. 1 nte ropServ і ces;
public class PInvokeClient
Il Функция Win32 MessageBoxС) кинет в user32.dll
[D11Iniport{"user32")]
public static extern int MessageBoxCint hwnd. String pText. String
pCaption. int uType):
public static int Ma іiifstnrig[] args) {
Il Создаем несколько переменных .NET для передачи Il функции Win32 MessageBoxO
String pText = "Hello World!": String pCaption - "PInvoke Test"; MessageBoxtO. pText, pCaption. 0):
return 0;
» '
Процесс обращения к внешнему традиционному модулю DLL (то есть модулю D LL, написанномуна С безвсякихС ОМ-элементов)начинается с объявления функции с ключевыми словами static и extern. (Это обязательно.) Обратите внимание, что при объявлении прототипа функции С мы должны, конечно, пользоваться типами данных .NET. Например, нельзя использовать типы данных char* и wchar_t* — вместо этого, как мы видим, используется тип System. Stri ng.
Кроме того, мы должны пометить этот прототип функции при помощи атрибута [Ollimport]. Как минимум, в значении этого атрибута мы должны указать имя модуля DLL, функцию из которого мы будем вызывать, как это у нас и сделано:
[Dil Importe"user32")]
publ ic static extern int NessagaBoxC. . .):
Тип DlUmportAttr bute определяет значительное количество открытых переменных (полей), которые можно использовать для настройки процесса вызова внешней функции. Эти поля представлены в табл. 12.2.
Чтобы задать эти значения для текущего объекта Dl 1 ImportAttribute, просто укажем каждую пару имя — значение в конструкторе класса. Конструктор Dil Import-Attribute принимает единственный параметр типа System. String:
class DTI ImportAttribute {
II Конструктор принимает переменную типа string, в которой будут содержаться // все пары имя поля - значение public Dil ImportAttribute (stringval):
І"
Понятно, что при таком подходе Dl ImportAttri bute абсолютно безразлично, в каком наборе и в какой последовательности мы укажем эти пары имя — значение.
Взаимодействие с модулями созданными на С 567
Строковое значение будет просмотрено целиком, и из него будут извлечены необходимые параметры.
Таблица 12.2. Поля типа DIIImportAttribute
Поле
CallingConvention
CharSet
EntryPolnt ExactSpelling
PreserveSig
SetLastError
Описание
Используется для определения соглашения о вызовах convention),
используемого при передаче аргументов метода
Определяет, как именно будут передаваться вызываемой функции строкові данные
Определяет имя или номер вызываемой функции
Если это поле будет иметь значение true, то никакие попытки служб PInvoke «догадаться», какое именно имя вызываемой функции имеется в виду (об этой особенности PInvoke — чуть позже), допускаться не будут: будет требоваться точное совпадение имени вызываемой функции с переданным именем
Если это поле будет иметь значение true (это значение используется ¦по умолчанию), сигнатура метода традиционной DLL не будегпреобразована в сигнатуру метода .NET при возврате HRESULT и дополнительных аргументов [out, retval]
Если это поле имеет значение true, это значит, что вызывающий может вызывать метод Win32 GetLastErrorO для определения того, возникла ли ошибка при выполнении метода. По умолчанию для этого поля используется значение false
Поле ExactSpelling
Первое поле Oi і Import, которое заслуживает особого рассмотрения, — это поле ExactSpel 1 і ng. Как нам уже известно (см. табл. 12.2), это поле определяет, будет ли требоваться точное соответствие между именем функции в ,NET и именем функции в традиционном модуле DLL. Например, если сказать по правде, то функции с именем Message8ox() в Win32 API нет. Вместо нее есть две функции - версия ANSI (MessageBoxAO) и функция Unicode (MessageBoxW). Поэтому, анализируя наш пример, можно прийти к выводу, что раз он работает, txactSpell ing имеет значение в false, и это — значение этого поля по умолчанию (что совершенно верно). Если вы установите для этого поля значение true:
[DIlImport("user32". ExactSpelling - true)]
public static extern int MessageBox(...): // Ой-ой...
то ничего хорошего не произойдет. Точнее, будет сгенерировано исключение Е.п-
tryPomtNotFoundExeepf on с объяснением, что точка входа '"'essageBox в модуле user32.ifll не обнаружена.
Предыдущая << 1 .. 222 223 224 225 226 227 < 228 > 229 230 231 232 233 234 .. 320 >> Следующая
Реклама
Авторские права © 2009 AdsNet. Все права защищены.
Rambler's Top100