Como: realizar realizar marshaling strings usando PInvoke
Este tópico explica como nativo funções que aceitam seqüências de caracteres de estilo C podem ser chamadas usando a seqüência de caracteres CLR digite sistema::String utilizando suporte a invocação de plataforma do .NET estrutura.O Visual C++ programadores são incentivados a usar os recursos de interoperabilidade C++ em vez disso (quando for possível) porque P/Invoke fornece relatórios de erro em time de compilar pouco, não é fortemente tipado e pode ser entediante implementar.Se a API não gerenciada é empacotada sistema autônomo uma DLL, e o código-fonte não está disponível, P/Invoke é a única opção, mas caso contrário, consulte Usando a interoperabilidade de C++ (PInvoke implícita).
Seqüências de caracteres gerenciadas e não gerenciadas são dispostas diferente na memória, para que passar cadeias de caracteres de funções gerenciadas para não gerenciado exige o MarshalAsAttribute atributo para instruir o compilador para inserir os mecanismos de conversão necessária para marshaling de dados de seqüência de caracteres corretamente e com segurança.
sistema autônomo ocorre com funções que usam apenas intrínseca tipos de dados, DllImportAttribute usado para declarar sistema autônomo pontos de entrada gerenciado para o nativo funções, mas--para passanado seqüências--em vez de definir esses entrada pontos sistema autônomo tirar 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 gerenciado que leva uma seqüência de caracteres, a MarshalAsAttribute atributo deve ser usado para indicar que o objeto String deve ser empacotado para o nativo funcionar sistema autônomo uma seqüência de caracteres de estilo C.
Exemplo
O código a seguir consiste em um não-gerenciados e um módulo gerenciado.O módulo não gerenciado é uma DLL que define uma função chamada TakesAString que aceita uma cadeia 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 define sistema autônomo tirar um sistema.String gerenciado em vez de um char *.The MarshalAsAttribute atributo é usado para indicar como o gerenciado seqüência de caracteres deve ser empacotada quando TakesAString é chamado.
O módulo gerenciado é compilado com/CLR, mas com/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 de seqüência de caracteres para ser construído no heap não gerenciada, para que as alterações efetuadas na seqüência de caracteres, a função nativa não serão refletidas na cópia gerenciada da seqüência de caracteres.
Observe que nenhuma parte da DLL seja exposto no código gerenciado via # tradicional diretiva include.Na verdade, a DLL é acessada no time de execução, então, problemas com funções importados com DllImport não serão detectados no momento da compilar.