Usando interop C++ (PInvoke implícito)

Ao contrário de outras linguagens .NET, Visual C++ tem suporte de interoperabilidade que permite que o código gerenciado e não gerenciado exista no mesmo aplicativo e mesmo no mesmo arquivo (com os pragmas gerenciados e não gerenciados). Isso permite que os desenvolvedores de Visual C++ integrem a funcionalidade do .NET a aplicativos Visual C++ existentes sem perturbar o restante do aplicativo.

Você também pode chamar funções não gerenciadas de um compiland gerenciado usando dllexport, DllImport.

O PInvoke implícito é útil quando você não precisa especificar como os parâmetros de função serão empacotados ou qualquer um dos outros detalhes que podem ser especificados ao chamar explicitamente DllImportAttribute.

Visual C++ fornece duas maneiras de interoperar as funções gerenciadas e não-gerenciadas:

o PInvoke explícito é suportado pelo .NET Framework e está disponível na maioria das linguagens .net. Mas como o nome sugere, a interoperabilidade de C++ é específica para Visual C++.

Interoperabilidade C++

A interoperabilidade C++ fornece melhor segurança de tipo e, normalmente, é menos entediante de implementar. No entanto, a interoperabilidade C++ não será uma opção se o código-fonte não gerenciado não estiver disponível ou para projetos de plataforma cruzada.

Interoperabilidade COM C++

Os recursos de interoperabilidade com suporte pelo Visual C++ oferecem uma vantagem específica sobre outras linguagens .NET quando se trata de interoperar com componentes COM. em vez de serem limitados às restrições do .NET Framework Tlbimp.exe (tipo de importador da biblioteca de tipos), como suporte limitado para tipos de dados e a exposição obrigatória de todos os membros de cada interface COM, a interoperabilidade C++ permite que os componentes com sejam acessados no e não exigem assemblies de interoperabilidade separados. ao contrário de Visual Basic e C#, Visual C++ pode usar objetos com diretamente usando os mecanismos com usuais (como CoCreateInstance e QueryInterface). Isso é possível devido a recursos de interoperabilidade do C++ que fazem com que o compilador insira automaticamente o código de transição para migrar de funções gerenciadas para não gerenciadas e de volta.

Usando a interoperabilidade C++, os componentes COM podem ser usados, pois eles normalmente são usados ou podem ser dispostos dentro de classes C++. Essas classes de wrapper são chamadas de wrappers callable de tempo de execução personalizados, ou CRCWs, e têm duas vantagens em relação ao uso de COM diretamente no código do aplicativo:

  • A classe resultante pode ser usada em idiomas diferentes de Visual C++.

  • Os detalhes da interface COM podem ser ocultados do código do cliente gerenciado. Os tipos de dados do .NET podem ser usados no lugar de tipos nativos, e os detalhes do marshaling de dados podem ser executados de forma transparente dentro do CRCW.

Independentemente de o COM ser usado diretamente ou por meio de um CRCW, tipos de argumento que não sejam simples, os tipos blittable devem ser empacotados.

Tipos blittable

Para APIs não gerenciadas que usam tipos simples e intrínsecos (consulte tipos de transferência de bits e não-blittable), nenhuma codificação especial é necessária porque esses tipos de dados têm a mesma representação na memória, mas os tipos de dados mais complexos exigem o marshaling explícito de dados. Para obter um exemplo, consulte como: chamar DLLs nativas do código gerenciado usando PInvoke.

Exemplo

// vcmcppv2_impl_dllimp.cpp
// compile with: /clr:pure user32.lib
using namespace System::Runtime::InteropServices;

// Implicit DLLImport specifying calling convention
extern "C" int __stdcall MessageBeep(int);

// explicit DLLImport needed here to use P/Invoke marshalling because
// System::String ^ is not the type of the first parameter to printf
[DllImport("msvcrt.dll", EntryPoint = "printf", CallingConvention = CallingConvention::Cdecl,  CharSet = CharSet::Ansi)]
// or just
// [DllImport("msvcrt.dll")]
int printf(System::String ^, ...);

int main() {
   // (string literals are System::String by default)
   printf("Begin beep\n");
   MessageBeep(100000);
   printf("Done\n");
}
Begin beep
Done

Nesta seção

Para obter informações sobre como usar delegados em um cenário de interoperabilidade, consulte delegar (extensões de componente do C++).

Confira também