Udostępnij za pośrednictwem


Jak: ciągi MARSZAŁEK przy użyciu funkcji PInvoke

Ten temat wyjaśnia, jak native funkcje, które przyjmują ciągi c styl można nazywane przy użyciu środowiska CLR typu string System::String używać.NET Framework platformy wywołać pomocy technicznej.Visual C++ programiści są zachęcani do zamiast korzystać z funkcji współdziałania z modelem C++ (jeśli możliwe), ponieważ P/Invoke zawiera niewiele raportowanie błędów kompilacji, nie jest typu bezpiecznej i może być uciążliwe do wdrożenia.Jeśli niezarządzanego API jest dostarczana jako biblioteki DLL, kod źródłowy nie jest dostępny, a P/Invoke jest tylko opcja, ale inaczej Za pomocą Interop C++ (niejawna PInvoke).

Ciągi zarządzanych i niezarządzanych określono inaczej w pamięci, więc przekazując ciągi z zarządzanych do niezarządzanych funkcji wymaga MarshalAsAttribute atrybutu, aby nakazać kompilatorowi, aby wstawić konwersji wymagane mechanizmy przekazywania międzyprocesowego dane ciągu poprawnie i bezpiecznie.

Podobnie jak w przypadku tylko typy danych wewnętrzne, użyj funkcji DllImportAttribute służy do deklaracji punkty wejścia zarządzanych w macierzystym funkcji, ale--przekazywania ciągi--zamiast definiowania tych punktów wejścia jako ciągi stylu języka C, dojście do podjęcia String można użyć zamiast tego typu.Powoduje to wyświetlenie kompilatora, aby wstawić kod, który wykonuje konwersję wymagane.Dla każdego argumentu funkcji w funkcji niezarządzanego, że ciąg znaków MarshalAsAttribute atrybut powinien być używany do wskazania, że obiekt ciąg należy zorganizować macierzystych funkcji jako ciąg w stylu języka C.

Przykład

Poniższy kod składa się z niezarządzanych i zarządzanych modułu.Moduł niezarządzanego to biblioteki DLL, która definiuje funkcję o nazwie TakesAString, która akceptuje ciąg ANSI C stylu w formie char |.Moduł zarządzany jest przywóz funkcji TakesAString, ale definiuje go jako biorąc zarządzanych System.String zamiast char * aplikacji wiersza polecenia.MarshalAsAttribute Atrybut jest używany do wskazania, jak należy zorganizować zarządzanych ciąg po wywołaniu TakesAString.

Moduł zarządzany jest kompilowana/CLR, ale/CLR: również czystego programu 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);
}

Technika ta powoduje kopię ciąg skonstruowano na stercie niezarządzanego, więc zmiany wprowadzone przez funkcję macierzystym ciąg nie jest odzwierciedlany w zarządzanych kopii łańcucha.

Uwaga, że żadna jego część biblioteki DLL jest narażony na kod zarządzany za pośrednictwem tradycyjnych # dołączona dyrektywa.W rzeczywistości, biblioteka DLL jest dostępny w czasie wykonywania, tak problemy z funkcjami przywożone z DllImport nie będą wykrywane w czasie kompilacji.

Zobacz też

Inne zasoby

Za pomocą jawnego PInvoke w C++ (atrybut DllImport)