Compartilhar via


Como: seqüências de empacotamento usando PInvoke

Este tópico explica como nativas funções que aceitam seqüências de caracteres de estilo c pode ser chamado usar o tipo de string do CLR System usando.Suporte de invocação de plataforma do NET Framework.Programadores do Visual C++ são incentivados a usar os recursos de interoperabilidade de C++ em vez disso (quando possível) porque P/Invoke fornece relatórios de erro em tempo de compilar pouco, não é tipo seguro e pode ser entediante implementar.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, mas caso contrário, consulte Usando interoperabilidade C++ (PInvoke implícita).

Gerenciado e seqüências de caracteres são dispostas diferente na memória, portanto passar seqüências de gerenciado para não gerenciadas funções requer o MarshalAsAttribute atributo para instruir o compilador a inserir os mecanismos de conversão necessária para empacotamento de dados de seqüência de caracteres corretamente e com segurança.

Como com funções que usam somente tipos de dados intrínseco, DllImportAttribute é usado para declarar os pontos de entrada gerenciado em funções nativas, mas – para passar cadeias de caracteres – em vez de definir esses pontos de entrada a obtenção de seqüências de caracteres de estilo C, um identificador para o String tipo pode ser usado em vez disso.Isso solicita que o compilador a inserir o código que executa a conversão necessária.Para cada argumento de função em uma função não gerenciada que usa uma seqüência de MarshalAsAttribute atributo deve ser usado para indicar que o objeto de seqüência de caracteres deve ser empacotado para a função nativa como uma seqüência de caracteres de estilo C.

Exemplo

O código a seguir consiste em uma não gerenciado e um módulo gerenciado.O módulo não gerenciado é uma DLL que define uma função chamada TakesAString que aceita uma seqüência ANSI de estilo c na forma de um char *.O módulo gerenciado é um aplicativo de linha de comando que importa a função TakesAString, mas define como tirar string gerenciado em vez de um char *.O MarshalAsAttribute atributo é usado para indicar como a cadeia gerenciada deve ser empacotada TakesAString é chamado.

O módulo gerenciado é compilado com /clr, mas /clr: pura funciona bem.

// TraditionalDll2.cpp
// compile with: /LD /EHsc
#include <windows.h>
#include <stdio.h>
#include <iostream>

using namespace std;

#define TRADITIONALDLL_EXPORTS
#ifdef TRADITIONALDLL_EXPORTS
#define TRADITIONALDLL_API __declspec(dllexport)
#else
#define TRADITIONALDLL_API __declspec(dllimport)
#endif

extern "C" {
   TRADITIONALDLL_API void TakesAString(char*);
}

void TakesAString(char* p) {
   printf_s("[unmanaged] %s\n", p);
}

// MarshalString.cpp
// compile with: /clr
using namespace System;
using namespace System::Runtime::InteropServices;

value struct TraditionalDLL
{
   [DllImport("TraditionalDLL2.dll")]
      static public void 
      TakesAString([MarshalAs(UnmanagedType::LPStr)]String^);
};

int main() {
   String^ s = gcnew String("sample string");
    Console::WriteLine("[managed] passing managed string to unmanaged function...");
   TraditionalDLL::TakesAString(s);
   Console::WriteLine("[managed] {0}", s);
}

Essa técnica faz com que uma cópia da seqüência a ser construído no heap não gerenciada, para que as alterações feitas pela função nativa a seqüência de caracteres não serão refletidas na cópia da seqüência de caracteres gerenciada.

Observe que nenhuma parte da DLL é exposto para código gerenciado via # tradicional incluir diretiva.Na verdade, a DLL é acessada no tempo de execução somente para problemas com funções importados com DllImport não serão detectados em tempo de compilação.

Consulte também

Outros recursos

Usando PInvoke Explicit no C++ (atributo DllImport)