Como: PInvoke usando de empacotar matrizes
Este tópico explica como nativas funções que aceitam a seqüências de caracteres de estilo c podem ser chamadas usando o tipo de seqüência de caracteres do CLR String usando.Suporte a invocação de plataforma do NET Framework. Programadores de Visual C++ são incentivados a usar os recursos de interoperabilidade de C++ em vez disso, (quando possível), porque fornece relatórios de erro de tempo de compilação pouco P/Invoke, não é um tipo seguro e pode ser entediante implementá. Se a API não gerenciada é empacotada como uma DLL e o código-fonte não está disponível, P/Invoke é a única opção (caso contrário, consulte Usar a interoperabilidade de C++ (PInvoke implícito)).
Exemplo
Porque as matrizes nativas e gerenciadas são dispostas diferente na memória, passar-os com êxito entre o limite gerenciado/requer a conversão ou empacotamento. Este tópico demonstra como uma matriz de itens de simples (blitable) pode ser passada para funções nativas do código gerenciado.
Como é verdadeiro de empacotamento de dados gerenciados/não gerenciados em geral, o DllImportAttribute atributo é usado para criar um ponto de entrada gerenciado para cada função nativa que será usado. No caso de funções que levam a matrizes como argumentos, o MarshalAsAttribute atributo deve ser usado também para especificar para o compilador como os dados serão empacotados. No exemplo a seguir, o LPArray enumeração é usada para indicar que o array gerenciado será empacotado como uma matriz de estilo C.
O código a seguir consiste em um não gerenciado e um módulo gerenciado. O módulo de não gerenciado é uma DLL que define uma função que aceita uma matriz de inteiros. O segundo módulo é um aplicativo gerenciado de linha de comando que importa essa função, mas define em termos de uma matriz gerenciada e usa o MarshalAsAttribute atributo para especificar que a matriz deve ser convertida para um array nativo quando chamado.
O módulo gerenciado é compilado com /clr mas /clr: puro também o works.
// TraditionalDll4.cpp
// compile with: /LD /EHsc
#include <iostream>
#define TRADITIONALDLL_EXPORTS
#ifdef TRADITIONALDLL_EXPORTS
#define TRADITIONALDLL_API __declspec(dllexport)
#else
#define TRADITIONALDLL_API __declspec(dllimport)
#endif
extern "C" {
TRADITIONALDLL_API void TakesAnArray(int len, int[]);
}
void TakesAnArray(int len, int a[]) {
printf_s("[unmanaged]\n");
for (int i=0; i<len; i++)
printf("%d = %d\n", i, a[i]);
}
// MarshalBlitArray.cpp
// compile with: /clr
using namespace System;
using namespace System::Runtime::InteropServices;
value struct TraditionalDLL {
[DllImport("TraditionalDLL4.dll")]
static public void TakesAnArray(
int len,[MarshalAs(UnmanagedType::LPArray)]array<int>^);
};
int main() {
array<int>^ b = gcnew array<int>(3);
b[0] = 11;
b[1] = 33;
b[2] = 55;
TraditionalDLL::TakesAnArray(3, b);
Console::WriteLine("[managed]");
for (int i=0; i<3; i++)
Console::WriteLine("{0} = {1}", i, b[i]);
}
Observe que nenhuma parte da DLL é exposto ao código gerenciado por meio do tradicional # incluir uma diretiva. Na verdade, porque a DLL é acessada em tempo de execução somente, problemas com funções importadas com DllImportAttribute não serão detectadas em tempo de compilação.