на начало
На главную страницу
Форум   

Статья :: Службы обращения к платформе: Plnvoke (Platform Invocation Services)


Службы обращения к платформе: Plnvoke (Platform Invocation Services)

Службы обращения к платформе, или Plnvoke (Platform Invocation Services,), делают неуправляемые экспортируемые динамически подключаемой библиотекой (DLL) функции доступными для управляемой программы клиента. Службы обращения к платформе Plnvoke (Platform Invocation Services) позволяют сделать это для любой управляемой программы, написанной на любом языке программирования .NET. Заметим, что Plnvoke является не именем класса или метода, а мнемоническим именем для Platform Invocation Services (Службы обращения к платформе). Службы обращения к платформе Plnvoke (Platform Invocation Services) следят за маршалингом между типами данных общеязыковой среды выполнения CLR и типами собственных данных, и играют роль моста, благодаря которому преодолеваются прочие различия между управляемой и неуправляемой средой запуска программ. Несмотря на то, что службы обращения к платформе PInvoke (Platform Invocation Services) изначально использовались для доступа к интерфейсам 32-разрядных Windows-приложений (Win32 API), они могут использоваться и для вызовов унаследованных динамически подключаемых библиотек (DLL). К сожалению, применение PInvoke (Platform Invocation Services, Службы обращения к платформе) в большинстве случаев оказывается дорогой с односторонним движением. Службы обращения к платформе можно использовать для вызова из управляемой программы неуправляемых функций динамически подключаемой библиотеки (DLL) и, конечно, для возврата в управляемую программу. Службы обращения к платформе PInvoke (Platform Invocation Services) используются для доступа к глобальным экспортированным функциям динамически подключаемых библиотек (DLL), поэтому, даже если динамически подключаемая библиотека (DLL) экспортирует методы класса, они остаются недоступными через PInvoke (Platform Invocation Services, Службы обращения к платформе).
В принципе, средств C++ достаточно, чтобы даже не задумываться о существовании служб обращения к платформе PInvoke (Platform Invocation Services). Ведь в отличие от других языков .NET, Visual C++ .NET позволяет смешивать управляемый и неуправляемый код непосредственно в вашей программе. Таким образом, чтобы вызвать функцию динамически подключаемой библиотеки (DLL) из кода на управляемом C++ вы можете просто вызвать собственный код на неуправляемом C++, который, в свою очередь, обычным образом вызовет неуправляемую функцию динамически подключаемой библиотеки (DLL). Однако вы можете использовать и службы обращения к платформе PInvoke (Platform Invocation Services) для непосредственного вызова из кода на управляемом C++ неуправляемого кода динамически подключаемой библиотеки (DLL), как это показано в следующем примере кода.

//PInvoke.срр
fusing <mscorlib.dll>
using namespace System;
// использование пространства имен Система;
using namespace System::Runtime::InteropServices;
// использование пространства имен
// Система::Время выполнения::InteropServices;
typedef void* HWND;
[Dlllmport("user32")]
extern "C" int MessageBoxA( // интерфейс 32-разрядных
// Windows-приложений (Win32 API)
HWND hWnd, // дескриптор окна владельца
String* pText, // текст окна сообщений
String* pCaption, // заголовок окна сообщений
unsigned int uType // стиль окна сообщений
);
void main(void) {
String* pText = L"Hello PInvoke!"; // Привет PInvoke!
String* pCaption = L"PInvoke Example"; // Пример PInvoke
MessageBoxA(0, pText, pCaption, 0); }

В результате выполнения этой программы будет выведено окно сообщения, показанное на рис. 15.7.

7.gif

Рис. 15.7. Это окно сообщения будет выведено при выполнении программы PInvoke.cpp

В приведенном примере PInvoke (Platform Invocation Services, Службы обращения к платформе) не показано, как службы обращения к платформе PInvoke (Platform Invocation Services) автоматически выполняют маршалинг выходных параметров. Это связано с тем, что MessageBox имеет только входные параметры. В следующем примере вызываются интерфейсы прикладных программ (API) GetComputerName и GetLastError посредством служб обращения к платформе PInvoke (Platform Invocation Services)
Первый параметр функции GetComputerName с именем IpBuffer, является выходным указателем на буфер, в который записывается строка с завершающим нулем, содержащая имя компьютера в случае успешного выполнения функции Второй параметр IpnSize является и входным, и выходным. В случае использования его в качестве входного параметра, в нем задается длина буфера IpBuffer в символах TCHAR. В случае использования его в качестве выходного параметра в нем указывается фактическая длина имени компьютера в символах TCHAR, которая содержится в IpBuffer, причем завершающий нулевой символ при подсчете длины не учитывается. Возвращаемое значение указывает, было ли успешным выполнение функции. Ненулевое значение указывает на ее успешное выполнение, а нулевое — на ошибку. Если возвращенное значение равно нулю, можно использовать функцию GetLastError для определения причины ошибки. Например, если буфер оказался недостаточно длинным для имени компьютера, эта функция вернет константу ERROR_BUFFER_OVERFLOW, имеющую значение 111. Если вы хотите попробовать самостоятельно использовать службы обращения к платформе PInvoke (Platform Invocation Services), и не будете против приложить некоторые усилия, то можете вызвать функцию интерфейса прикладных программ (API) FormatMessage для перевода этого номера ошибки в более осмысленную строку. Если вы это сделаете, и в достаточной мере укоротите длину буфера, то получите описание ошибки: "The File name is too long" ("Имя файла слишком длинное"). Прототипы функций GetComputerName и GetLastError приведены ниже:

BOOL GetComputerName( // ЛОГИЧЕСКАЯ (БУЛЕВА)
LPTSTR IpBuffer, // имя компьютера
LPDWORD IpnSize // размер буфера для имени
) ;
DWORD GetLastError(VOID) ;

В следующем примере показано, как вызвать функции GetLastError и GetComputerName из кода на управляемом C++ с помощью служб обращения к платформе РInvoke (Platform Invocation Services). Обе эти функции интерфейса прикладного программирования находятся в библиотеке Kernel32 .dll, поэтому атрибут [Dlllmport ("Kernel32" ) ] использован в обоих случаях. Заметим, что маршалинг для каждого выходного параметра выполняется автоматически. Хотя это и не показано в данном простом примере, для управления деталями маршалинга, выполняемого службами обращения к платформе PInvoke (Platform Invocation Services), можно использовать атрибуты. Впрочем, это необходимо только в том случае, если маршалинг, выполняемый по умолчанию службами обращения к платформе PInvoke (Platform Invocation Services), является неудовлетворительным.

//PInvokeOutParam.cpp
fusing <mscorlib.dll>
using namespace System;
// использование пространства имен Система;
using namespace System::Runtime::InteropServices;
// использование пространства имен
// Система::Время выполнения::InteropServices;
typedef int BOOL; // ЛОГИЧЕСКИЙ (БУЛЕВ)
typedef unsigned long DWORD; // без знака
#define MAX_COMPUTERNAME_LENGTH 31
[Dlllmport("Kernel32")]
extern "C" BOOL GetComputerName(
signed char *lpBuffer, UInt32* IpnSize); // символ
// со знаком
*lpBuffer
[Dlllmport("Kernel32")]
extern "C" DWORD GetLastError();
void main(void) {
signed char * IpBuffer = // символ со знаком
new signed char[MAX_COMPUTERNAME_LENGTH + 1]; // новый символ
// со знаком
UInt32 size = MAX_COMPUTERNAME_LENGTH + 1; // размер
BOOL bResult = GetComputerName(IpBuffer, Ssize);
if (bResult)
{
String *pstrComputerName = // Строка
new String((signed char *)IpBuffer); // новая Строка ((символ со знаком *)
IpBuffer);
Console::WriteLine(
"Computer Name: {0}", pstrComputerName); // Имя компьютера
}
else
{
DWORD dwLastError = GetLastError ();
Console::WriteLine(
"Last Error: {0}", _box(dwLastError)); // Последняя
// ошибка
}
}

Когда вы запустите на выполнение пример PInvokeOutParam, то увидите нечто подобное приведенному ниже, за исключением того, что будет указано реальное имя вашего компьютера, а не моего.

Computer Name: PT-2HBHVPJUGOT9


Службы обращения к платформе: Plnvoke (Platform Invocation Services)

страницы в данном разделе 
Глава 15. Смешивание управляемого и неуправляемого кода Смешивание управляемого и неуправляемого кода
Сравнение управляемого и неуправляемого кода Причины смешивания управляемого и неуправляемого кодов
Неуправляемый или опасный? Управляемые и неуправляемые ссылки и типы значений
Ограничения на использование управляемых типов в C++ Вызов управляемого кода из неуправляемого и обратный вызов
Сравнение программирования на C++ с использованием модели компонентных объектов Microsoft (COM) и .NET Доступ из управляемого кода к компонентам, построенным на основе модели компонентных объектов Microsoft (COM)
Сервисная программа Tibinp. ехе Унаследованный компонент на основе модели компонентных объектов Microsoft (COM)
Действующий клиент на основе модели компонентных объектов Microsoft (COM) Создание клиента на основе модели компонентных объектов Microsoft (COM) с помощью управляемого C++
Разработка управляемого клиента на основе модели компонентных объектов Microsoft (COM) с помощью С# Создание с помощью управляемого C++ клиента на основе модели компонентных объектов Microsoft (COM) без метаданных
Создание с помощью С# управляемого клиента на основе модели компонентных объектов Microsoft (COM) без метаданных Доступ к управляемым компонентам из клиентов на основе модели компонентных объектов Microsoft (COM)
Раннее связывание клиента на основе модели компонентных объектов Microsoft (COM) с компонентами .NET Динамическое связывание клиента на основе модели компонентных объектов Microsoft (COM) с компонентами .NET
Явное определение интерфейса Службы обращения к платформе: Plnvoke (Platform Invocation Services)
Резюме >  


Содержание сайта (выборка)
Apache
Протоколы TCP/IP (принципы, протоколы и архитектура)



PHP, PELR, JSP
PHP
JavaServer Pages (JSP)

Базы данных
Основы mysql
СУБД INFORMIX
СУБД POSTGRES
Основы проектирования реляционных баз данных

HTML, javascript
Спецификация HTML 4.01
Каскадные Таблицы Стилей, Уровень 2
Клиентский JavaScript. Справочник.
JavaScript руководство пользователя
Серверный JavaScript 1.4. Руководство по Использованию.

Паскаль, C, C++, C#
GCC (примеры)
FAQ Валентинa Озеровa DELPHI
C



 
© faq.pp.ru, справочник программиста