Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Você pode chamar funções nativas que aceitam cadeias de caracteres no estilo C usando o tipo String de cadeia de caracteres CLR ao usar o suporte a .NET Framework Platform Invoke (P/Invoke). Recomendamos que você use os recursos de interoperabilidade C++ em vez de P/Invoke quando possível. P/Invoke fornece poucos relatórios de erros em tempo de compilação, não é seguro para digitação e pode ser tedioso de implementar. Se a API não gerenciada for empacotada como uma DLL e o código-fonte não estiver disponível, P/Invoke será a única opção. Caso contrário, consulte a seção Interoperabilidade com C++ (P/Invoke implícito)).
Exemplo
Como matrizes nativas e gerenciadas são dispostas de forma diferente na memória, passá-las com êxito pelo limite gerenciado/não gerenciado requer conversão ou marshaling. Este artigo demonstra como uma matriz de itens simples (blitable) pode ser passada para funções nativas a partir de código gerenciado.
Como acontece com o 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 usada. Em funções que usam matrizes como argumentos, o MarshalAsAttribute atributo deve ser usado para especificar como organizar os dados. No exemplo a seguir, a UnmanagedType enumeração é usada para indicar que a matriz gerenciada é empacotada como uma matriz de estilo C.
O código a seguir consiste em um módulo não gerenciado e um módulo gerenciado. O módulo não gerenciado é uma DLL que define uma função que aceita uma matriz de inteiros. O segundo módulo é um aplicativo de linha de comando gerenciado que importa essa função, mas a define em termos de uma matriz gerenciada. Ele usa o MarshalAsAttribute atributo para especificar que a matriz deve ser convertida em uma matriz nativa quando chamada.
// 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]);
}
O módulo gerenciado é compilado usando /clr.
// 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]);
}
Nenhuma parte da DLL é exposta ao código gerenciado por meio da diretiva tradicional #include . Na verdade, como a DLL é acessada apenas em tempo de execução, problemas em funções importadas usando DllImportAttribute não podem ser detetados em tempo de compilação.