Megosztás a következőn keresztül:


Útmutató: Karakterláncok kezelése a P/Invoke használatával

A C stílusú sztringeket elfogadó natív függvények a CLR-sztringtípussal System::String hívhatók meg a .NET-keretrendszer platformhívási (P/Invoke) támogatásával. Javasoljuk, hogy ha lehetséges, használja a C++ Interop funkciókat a P/Invoke helyett. mivel a P/Invoke kevés fordítási idejű hibajelentést biztosít, nem típusbiztos, és a implementálás is fáradságos lehet. Ha a nem felügyelt API DLL-ként van csomagolva, és a forráskód nem érhető el, akkor a P/Invoke az egyetlen lehetőség. Ellenkező esetben lásd: C++ Interop (Implicit P/Invoke) használata.

A felügyelt és a nem felügyelt sztringek eltérően vannak elhelyezve a memóriában, ezért a felügyelt és a nem felügyelt függvények közötti sztringek átadása megköveteli az MarshalAsAttribute attribútumot, hogy utasítsa a fordítót, hogy szúrja be a sztringadatok helyes és biztonságos megőrzéséhez szükséges átalakítási mechanizmusokat.

A csak belső adattípusokat DllImportAttribute használó függvényekhez hasonlóan a felügyelt belépési pontok a natív függvényekbe való deklarálásához is használhatók. Azok a függvények, amelyek stringeket adnak át, használhatnak egy leírót a String típushoz ahelyett, hogy ezeket a belépési pontokat C-stílusú stringekként definiálják. Ezzel a típussal a fordító beszúrja a szükséges átalakítást végrehajtó kódot. A sztringet használó nem felügyelt függvények minden egyes függvényargumentumához használja az MarshalAsAttribute attribútumot, amely azt jelzi, hogy az String objektumot C stílusú sztringként kell a natív függvénybe helyezni.

A marshaler egy rejtett burkoló rutinnal csomagolja a kezeletlen függvény hívását. A wrapper-függvény rögzíti és átmásolja a felügyelt karakterláncot egy helyileg lefoglalt karakterláncba a nem felügyelt környezetben. Ezt követően a rendszer átadja a helyi másolatot a nem felügyelt függvénynek. Amikor a nem felügyelt függvény visszatér, a burkoló törli az erőforrást. Vagy ha a veremen volt, akkor az visszakerül, amikor a burkoló kikerül a hatókörből. A nem felügyelt függvény nem felelős ezért a memóriáért. A nem felügyelt kód csak a saját CRT által beállított veremterületen hoz létre és töröl memóriát, így az adattovábbítóval soha nem lesz probléma egy másik CRT-verzióval.

Ha a nem felügyelt függvény sztringet ad vissza akár visszatérési értékként, akár kimeneti paraméterként, a marshaler átmásolja egy új felügyelt sztringbe, majd felszabadítja a memóriát. További információkért lásd: Alapértelmezett adatkezelési viselkedés és Adatkezelés Platform Invoke használatával.

példa

A következő kód egy nem felügyelt modulból és egy felügyelt modulból áll. A nem felügyelt modul egy DLL, amely egy úgynevezett TakesAStringfüggvényt határoz meg. TakesAString C-stílusú karakterláncot fogad el egy char* formájában.

// 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);
}

A felügyelt modul egy parancssori alkalmazás, amely importálja a TakesAString függvényt, de úgy határozza meg, hogy a függvény System.String-et felügyeltként használja a char* helyett. Az MarshalAsAttribute attribútum azt jelzi, hogyan kell marshalelni a felügyelt sztringet, amikor a TakesAString meg van hívva.

// 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);
}

Ez a technika a sztring egy másolatát hozza létre és helyezi a nem felügyelt halomra, így a natív függvény által a sztringen végrehajtott módosítások nem jelennek meg a sztring felügyelt másolatán.

A DLL egyetlen része sem érhető el a felügyelt kódnak a hagyományos #include irányelv által. Valójában a DLL csak futtatókörnyezetben érhető el, így a használatával DllImport importált függvényekkel kapcsolatos problémák fordításkor nem észlelhetők.

Lásd még

Explicit P/Invoke használata c++ (DllImport attribútum) nyelven