Data Marshaling usando Managed Code Calling Marshaling Data with Platform Invoke

  • 03/20/2019
  • 5 minutos de tempo de leitura
    • g
    • o
    • O
    • S

Para chamar funções exportadas de uma biblioteca não gerida, a .Para chamar funções exportadas de uma biblioteca não gerida, uma aplicação .NET Framework requer um protótipo de função em código gerido que represente a função não gerida. Para criar um protótipo que permita a invocação da plataforma para ordenar correctamente os dados, é necessário fazer o seguinte:

  • p>aplicar o DllImportAttribute à função ou método estático em código gerido.Aplicar o atributo DllImportAttribute à função ou método estático no código gerido.
  • p>Substitute managed data types for unmanaged data types.Substituir tipos de dados geridos por tipos de dados não geridos.

P>Pode usar a documentação fornecida com uma função não gerida para construir um protótipo gerido equivalente aplicando o atributo com os seus campos opcionais e substituindo os tipos de dados geridos por tipos não geridos. Para instruções sobre como aplicar o tributo DllImportAttribute, ver Funções DLL Consumir Não Gerido.

Esta secção fornece amostras que demonstram como criar protótipos de funções geridas para passar argumentos e receber valores de retorno de funções exportadas por bibliotecas não geridas. As amostras também demonstram quando utilizar o atributo MarshalAsAttribute e a classe Marshal para explicitamente marshalar dados.

Tipos de dados de chamadas de código não geridasPlataforma de invocação de tipos de dados

A tabela seguinte lista os tipos de dados usados nas APIs do Windows e funções do estilo C. Muitas bibliotecas não geridas contêm funções que passam estes tipos de dados como parâmetros e valores de retorno. A terceira coluna lista o tipo ou classe de valor incorporado na estrutura .NET correspondente que utiliza no código gerido. Em alguns casos, pode substituir um tipo do mesmo tamanho pelo tipo listado na tabela.

>>Sistema.Vazio

SHORT

>Sistema.UInt16

INT

>UINT>>unsigned int>Sistema.UInt32

>>LONG

>Sistema.Int32

>>BOOL>>long> System.Boolean ou System.Int32System.Boolean ou System.Int32

>System.UInt32

>>ULONG>>unsigned long>Sistema.UInt32

>>CHAR>char>System.Char

>>char *

>DOUBLE

>Sistema.Double

Tipo não gerido em APIs do Windows Tipo não gerido em APIs do Windows Tipo não gerido em linguagem C Tipo não gerido em linguagem C Tipo gerido Tipo gerido DescriptionDescription
VOID void Aplicado a uma função que não devolve um valor. Aplicado a uma função que não devolve um valor.
HANDLE void * System.IntPtr ou System.UIntPtrSystem.IntPtr ou System.UIntPtr 32-bit em sistemas operativos Windows de 32-bit, 64-bit em sistemas operativos Windows de 64-bit.32 bits em sistemas operativos Windows de 32 bits, 64 bits em sistemas operativos Windows de 64 bits.
BYTE unsigned char Sistema.Byte 8 bits8 bits
short Sistema.Int16 16 bits16 bits
WORD unsigned short 16 bits16 bits
int System.Int32 32 bits32 bits
32 bits32 bits
long 32 bits32 bits
32 bits32 bits
DWORD unsigned long 32 bits32 bits
32 bits32 bits
Décorer avec ANSI.Decorate with ANSI.
WCHAR wchar_t System.Char Decorador avec Unicode.Decore com Unicode.
LPSTR System.String ou System.Text.StringBuilderSystem.String ou System.Text.StringBuilder Décorer avec ANSI.Decorate with ANSI.
LPCSTR const char * System.String ou System.Text.StringBuilderSystem.String ou System.Text.StringBuilder Décorer avec ANSI.Decorate with ANSI.
LPWSTR wchar_t * System.String ou System.Text.StringBuilderSystem.String ou System.Text.StringBuilder Décorer avec Unicode.Decorate with Unicode.
LPCWSTR const wchar_t * System.String ou System.Text.StringBuilderSystem.String ou System.Text.StringBuilder Décorer avec Unicode.Decorate with Unicode.
FLOAT float System.Simples 32 bits32 bits
double 64 bits64 bits

Pour les types correspondants en Visual Basic, C# et C+++, consultez Introduction à la bibliothèque de classes .NET Framework.Para os tipos correspondentes em Visual Basic, C#, e C++, consultez Introduction to the .NET Framework Class Library.

PinvokeLib.dllPinvokeLib.dll

Le code suivant définit les fonctions de bibliothèque fournies par Pinvoke.dll.O seguinte código define as funções da biblioteca fornecidas por Pinvoke.dll. De nombreux exemples décrits dans cette section appellent cette bibliothèque.Many samples described in this section call this library.

ExempleExample

// PInvokeLib.cpp : Defines the entry point for the DLL application.//#define PINVOKELIB_EXPORTS#include "PInvokeLib.h"#include <strsafe.h>#include <objbase.h>#include <stdio.h>#pragma comment(lib,"ole32.lib")BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ){ switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE;}//******************************************************************// This is the constructor of a class that has been exported.CTestClass::CTestClass(){ m_member = 1;}int CTestClass::DoSomething( int i ){ return i*i + m_member;}PINVOKELIB_API CTestClass* CreateTestClass(){ return new CTestClass();}PINVOKELIB_API void DeleteTestClass( CTestClass* instance ){ delete instance;}//******************************************************************PINVOKELIB_API int TestArrayOfInts( int* pArray, int size ){ int result = 0; for ( int i = 0; i < size; i++ ) { result += pArray; pArray += 100; } return result;}//******************************************************************PINVOKELIB_API int TestRefArrayOfInts( int** ppArray, int* pSize ){ int result = 0; // CoTaskMemAlloc must be used instead of the new operator // because code on the managed side will call Marshal.FreeCoTaskMem // to free this memory. int* newArray = (int*)CoTaskMemAlloc( sizeof(int) * 5 ); for ( int i = 0; i < *pSize; i++ ) { result += (*ppArray); } for ( int j = 0; j < 5; j++ ) { newArray = (*ppArray) + 100; } CoTaskMemFree( *ppArray ); *ppArray = newArray; *pSize = 5; return result;}//******************************************************************PINVOKELIB_API int TestMatrixOfInts( int pMatrix, int row ){ int result = 0; for ( int i = 0; i < row; i++ ) { for ( int j = 0; j < COL_DIM; j++ ) { result += pMatrix; pMatrix += 100; } } return result;}//******************************************************************PINVOKELIB_API int TestArrayOfStrings( char* ppStrArray, int count ){ int result = 0; STRSAFE_LPSTR temp; size_t len; const size_t alloc_size = sizeof(char) * 10; for ( int i = 0; i < count; i++ ) { len = 0; StringCchLengthA( ppStrArray, STRSAFE_MAX_CCH, &len ); result += len; temp = (STRSAFE_LPSTR)CoTaskMemAlloc( alloc_size ); StringCchCopyA( temp, alloc_size, (STRSAFE_LPCSTR)"123456789" ); // CoTaskMemFree must be used instead of delete to free memory. CoTaskMemFree( ppStrArray ); ppStrArray = (char *) temp; } return result;}//******************************************************************PINVOKELIB_API int TestArrayOfStructs( MYPOINT* pPointArray, int size ){ int result = 0; MYPOINT* pCur = pPointArray; for ( int i = 0; i < size; i++ ) { result += pCur->x + pCur->y; pCur->y = 0; pCur++; } return result;}//******************************************************************PINVOKELIB_API int TestStructInStruct( MYPERSON2* pPerson2 ){ size_t len = 0; StringCchLengthA( pPerson2->person->last, STRSAFE_MAX_CCH, &len ); len = sizeof(char) * ( len + 2 ) + 1; STRSAFE_LPSTR temp = (STRSAFE_LPSTR)CoTaskMemAlloc( len ); StringCchCopyA( temp, len, (STRSAFE_LPSTR)"Mc" ); StringCbCatA( temp, len, (STRSAFE_LPSTR)pPerson2->person->last ); CoTaskMemFree( pPerson2->person->last ); pPerson2->person->last = (char *)temp; return pPerson2->age;}//******************************************************************PINVOKELIB_API int TestArrayOfStructs2( MYPERSON* pPersonArray, int size ){ int result = 0; MYPERSON* pCur = pPersonArray; STRSAFE_LPSTR temp; size_t len; for ( int i = 0; i < size; i++ ) { len = 0; StringCchLengthA( pCur->first, STRSAFE_MAX_CCH, &len ); len++; result += len; len = 0; StringCchLengthA( pCur->last, STRSAFE_MAX_CCH, &len ); len++; result += len; len = sizeof(char) * ( len + 2 ); temp = (STRSAFE_LPSTR)CoTaskMemAlloc( len ); StringCchCopyA( temp, len, (STRSAFE_LPCSTR)"Mc" ); StringCbCatA( temp, len, (STRSAFE_LPCSTR)pCur->last ); result += 2; // CoTaskMemFree must be used instead of delete to free memory. CoTaskMemFree( pCur->last ); pCur->last = (char *)temp; pCur++; } return result;}//******************************************************************PINVOKELIB_API void TestStructInStruct3( MYPERSON3 person3 ){ printf( "\n\nperson passed by value:\n" ); printf( "first = %s last = %s age = %i\n\n", person3.person.first, person3.person.last, person3.age );}//*********************************************************************PINVOKELIB_API void TestUnion( MYUNION u, int type ){ if ( ( type != 1 ) && ( type != 2 ) ) { return; } if ( type == 1 ) { printf( "\n\ninteger passed: %i", u.i ); } else if ( type == 2 ) { printf( "\n\ndouble passed: %f", u.d ); }}//******************************************************************PINVOKELIB_API void TestUnion2( MYUNION2 u, int type ){ if ( ( type != 1 ) && ( type != 2 ) ) { return; } if ( type == 1 ) { printf( "\n\ninteger passed: %i", u.i ); } else if ( type == 2 ) { printf( "\n\nstring passed: %s", u.str ); }}//******************************************************************PINVOKELIB_API void TestCallBack( FPTR pf, int value ){ printf( "\nReceived value: %i", value ); printf( "\nPassing to callback..." ); bool res = (*pf)(value); if ( res ) { printf( "Callback returned true.\n" ); } else { printf( "Callback returned false.\n" ); }}//******************************************************************PINVOKELIB_API void TestCallBack2( FPTR2 pf2, char* value ){ printf( "\nReceived value: %s", value ); printf( "\nPassing to callback..." ); bool res = (*pf2)(value); if ( res ) { printf( "Callback2 returned true.\n" ); } else { printf( "Callback2 returned false.\n" ); }}//******************************************************************PINVOKELIB_API void TestStringInStruct( MYSTRSTRUCT* pStruct ){ wprintf( L"\nUnicode buffer content: %s\n", pStruct->buffer ); // Assuming that the buffer is big enough. StringCbCatW( pStruct->buffer, pStruct->size, (STRSAFE_LPWSTR)L"++" );}//******************************************************************PINVOKELIB_API void TestStringInStructAnsi( MYSTRSTRUCT2* pStruct ){ printf( "\nAnsi buffer content: %s\n", pStruct->buffer ); // Assuming that the buffer is big enough. StringCbCatA( (STRSAFE_LPSTR) pStruct->buffer, pStruct->size, (STRSAFE_LPSTR)"++" );}//******************************************************************PINVOKELIB_API void TestOutArrayOfStructs( int* pSize, MYSTRSTRUCT2** ppStruct ){ const int cArraySize = 5; *pSize = 0; *ppStruct = (MYSTRSTRUCT2*)CoTaskMemAlloc( cArraySize * sizeof( MYSTRSTRUCT2 )); if ( ppStruct != NULL ) { MYSTRSTRUCT2* pCurStruct = *ppStruct; LPSTR buffer; *pSize = cArraySize; STRSAFE_LPCSTR teststr = "***"; size_t len = 0; StringCchLengthA(teststr, STRSAFE_MAX_CCH, &len); len++; for ( int i = 0; i < cArraySize; i++, pCurStruct++ ) { pCurStruct->size = len; buffer = (LPSTR)CoTaskMemAlloc( len ); StringCchCopyA( buffer, len, teststr ); pCurStruct->buffer = (char *)buffer; } }}//************************************************************************PINVOKELIB_API char * TestStringAsResult(){ const size_t alloc_size = 64; STRSAFE_LPSTR result = (STRSAFE_LPSTR)CoTaskMemAlloc( alloc_size ); STRSAFE_LPCSTR teststr = "This is return value"; StringCchCopyA( result, alloc_size, teststr ); return (char *) result;}//************************************************************************PINVOKELIB_API void SetData( DataType typ, void* object ){ switch ( typ ) { case DT_I2: printf( "Short %i\n", *((short*)object) ); break; case DT_I4: printf( "Long %i\n", *((long*)object) ); break; case DT_R4: printf( "Float %f\n", *((float*)object) ); break; case DT_R8: printf( "Double %f\n", *((double*)object) ); break; case DT_STR: printf( "String %s\n", (char*)object ); break; default: printf( "Unknown type" ); break; }}//************************************************************************PINVOKELIB_API void TestArrayInStruct( MYARRAYSTRUCT* pStruct ){ pStruct->flag = true; pStruct->vals += 100; pStruct->vals += 100; pStruct->vals += 100;}

// PInvokeLib.h : The header file for the DLL application.//#pragma once#define WIN32_LEAN_AND_MEAN#include <windows.h>// The following ifdef block is the standard way of creating macros which make exporting// from a DLL simpler. All files within this DLL are compiled with the PINVOKELIB_EXPORTS// symbol defined on the command line. this symbol should not be defined on any project// that uses this DLL. This way any other project whose source files include this file see// PINVOKELIB_API functions as being imported from a DLL, wheras this DLL sees symbols// defined with this macro as being exported.#ifdef PINVOKELIB_EXPORTS#define PINVOKELIB_API __declspec(dllexport)#else#define PINVOKELIB_API __declspec(dllimport)#endif// Define the test structurestypedef struct _MYPOINT{ int x; int y;} MYPOINT;typedef struct _MYPERSON{ char* first; char* last;} MYPERSON;typedef struct _MYPERSON2{ MYPERSON* person; int age;} MYPERSON2;typedef struct _MYPERSON3{ MYPERSON person; int age;} MYPERSON3;union MYUNION{ int i; double d;};union MYUNION2{ int i; char str;};typedef struct _MYSTRSTRUCT{ wchar_t* buffer; UINT size;} MYSTRSTRUCT;typedef struct _MYSTRSTRUCT2{ char* buffer; UINT size;} MYSTRSTRUCT2;typedef struct _MYARRAYSTRUCT{ bool flag; int vals;} MYARRAYSTRUCT;// constants and pointer definitionsconst int COL_DIM = 5;typedef bool (CALLBACK *FPTR)( int i );typedef bool (CALLBACK *FPTR2)( char* str );// Data type codesenum DataType{ DT_I2 = 1, DT_I4, DT_R4, DT_R8, DT_STR};// This is an exported class.class PINVOKELIB_API CTestClass{public: CTestClass( void ); int DoSomething( int i );private: int m_member;};// Exports for PInvokeLib.dll#ifdef __cplusplusextern "C"{#endifPINVOKELIB_API CTestClass* CreateTestClass();PINVOKELIB_API void DeleteTestClass( CTestClass* instance );PINVOKELIB_API int TestArrayOfInts( int* pArray, int size );PINVOKELIB_API int TestRefArrayOfInts( int** ppArray, int* pSize );PINVOKELIB_API int TestMatrixOfInts( int pMatrix, int row );PINVOKELIB_API int TestArrayOfStrings( char* ppStrArray, int size );PINVOKELIB_API int TestArrayOfStructs( MYPOINT* pPointArray, int size );PINVOKELIB_API int TestArrayOfStructs2( MYPERSON* pPersonArray, int size );PINVOKELIB_API int TestStructInStruct( MYPERSON2* pPerson2 );PINVOKELIB_API void TestStructInStruct3( MYPERSON3 person3 );PINVOKELIB_API void TestUnion( MYUNION u, int type );PINVOKELIB_API void TestUnion2( MYUNION2 u, int type );PINVOKELIB_API void TestCallBack( FPTR pf, int value );PINVOKELIB_API void TestCallBack2( FPTR2 pf2, char* value );// buffer is an in/out paramPINVOKELIB_API void TestStringInStruct( MYSTRSTRUCT* pStruct );// buffer is in/out paramPINVOKELIB_API void TestStringInStructAnsi( MYSTRSTRUCT2* pStruct );PINVOKELIB_API void TestOutArrayOfStructs( int* pSize, MYSTRSTRUCT2** ppStruct );PINVOKELIB_API char* TestStringAsResult();PINVOKELIB_API void SetData( DataType typ, void* object );PINVOKELIB_API void TestArrayInStruct( MYARRAYSTRUCT* pStruct );#ifdef __cplusplus}#endif

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *