Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
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