Como: PInvoke usando de empacotamento de Strings
Este tópico explica como nativas funções que aceitam seqüências de caracteres de estilo c pode ser chamado usando o tipo de seqüência de caracteres CLR System:: string usando.Suporte de 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, o código-fonte não está disponível e P/Invoke é a única opção, mas caso contrário, consulte Usar a interoperabilidade de C++ (PInvoke implícito).
Gerenciado e seqüências de caracteres são dispostas diferente na memória, assim, passando a seqüências de caracteres de gerenciado para funções não gerenciadas requer o MarshalAsAttribute atributo para instruir o compilador para inserir os mecanismos de conversão necessária para o empacotamento de dados de seqüência corretamente e com segurança.
Como ocorre com as funções que usam somente tipos de dados intrínseca, DllImportAttribute é usada para declarar os pontos de entrada de gerenciado para as 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 leva uma seqüência de caracteres, o 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 um não gerenciado e um módulo gerenciado. O módulo de não gerenciado é uma DLL que define uma função chamada TakesAString que aceita uma seqüência de caracteres ANSI do estilo c na forma de um char *. O módulo gerenciado é um aplicativo de linha de comando que importa a função TakesAString, mas a define como tirar uma String gerenciada em vez de um char *. O MarshalAsAttribute atributo é usado para indicar como a cadeia gerenciada deve ser empacotada quando é chamado TakesAString.
O módulo gerenciado é compilado com /clr mas /clr: puro também o works.
// 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 gerenciado, 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 ao código gerenciado por meio do tradicional # incluir uma diretiva. Na verdade, a DLL é acessada no tempo de execução somente para problemas com funções importadas com DllImport não serão detectadas em tempo de compilação.