Службы обращения к платформе: Plnvoke (Platform Invocation Services). Резюме.
Если вы хотите попробовать самостоятельно использовать службы обращения к платформе 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
Резюме
Эта глава посвящена смешиванию управляемого и неуправляемого кода с помощью Visual C++ .NET. Мы рассмотрели методы вызова неуправляемым кодом управляемого кода и методы вызова управляемым кодом неуправляемого кода в рамках одного исходного файла. Затем мы рассмотрели вызов из среды .NET существующих компонентов на основе модели компонентных объектов Microsoft (COM), а также вызов из среды модели компонентных объектов Microsoft (COM) компонентов .NET, с помощью как раннего, так и динамического связывания. В заключение мы рассмотрели использование служб обращения к платформе Plnvoke (Platform Invocation Services) и увидели, как осуществляется автоматический маршалинг входных и выходных параметров.
Мы подошли к концу большого путешествия, которое, следует полагать, будет не последним путешествием по миру .NET. Мы надеемся, что оно вам понравилось. Желаем успехов в реализации ваших проектов на платформе .NET!