Za tako nešto je C++/CLI uglavnom i namenjen.
U principu, sledeće stvari su glavne:
- implicitno mapiranje osnovnih unmanaged tipova u managed tipove:
Code:
void f(int x)
{
// ...
}
void f(long x)
{
// ...
}
Savršeno validan overloading u C++-u. Takođe, ove dve funkcije mogu da se kompajliraju kao managed kod i overloading će raditi opet savršeno iako se i
int i
long mapiraju u System::Int32 (to se razrešava specijalnim modifierom nad argumentom u drugoj funkciji
f).
- mešanje (komponovanje) C++ i .NET klasa:
Što će reći, moguće je da C++ klasa sadrži polje koje je handle na .NET objekat (pogledaj gcroot i auto_gcroot templejte, mislim da su u vcclr.h).
Obratna stvar je isto moguća:
Code:
ref class MojTip
{
public:
std::string s1; // nije validno
std::string *s2; // validno
};
Prva stvar (s1) nije validna zato što se std::string kreira na unmanaged heapu, te je nemoguće kreirati instancu klase MojTip jer GC ne zna ništa (tj. ne upravlja) o unmanaged heapu gde se nalazi s1. Dok pokazivač (s2) bez problema može da postoji na managed heapu. Takođe, nemoguće je uzeti adresu (&) nekog atributa i smestiti je u nativni pokazivač jer GC "šeta" managed instance u memoriji. U tom smislu, pogledaj i
interior_ptr templejt.
- prosleđivanje managed memorije unmanaged funkciji.
Da bi neka funkcija mogla slobodno da koristi native pokazivač na neko parče managed memorije, moraš nekako istu i da fiksiraš (tj. da privremeno "zabraniš" GC-u da je pomera). Pogledaj pin_ptr.
---
String iz tvog primera je moguće konvertovati u std::string uz pomoć Marshall klase koja se nalazi unutar System.Runtime.InteropServices. Takođe je moguće kreirati sopstveni marshalling.
Pozivanje managed koda iz unmanaged koda i obratno je moguće (i transparentno je u C++/CLI-u), ali treba biti obazriv koji compilation model koristiš nad nekim kodom i treba biti svestan da postoji overhead (pošto takva tranzicija izaziva kreiranje malih thunk-ova koji se pozivaju kako bi sve to uspelo). Kada je u pitanju recimo managed -> unmanaged tranzicija, u većini slučajeva ćeš dobiti i mnogo efikasniji kod nego što je to slučaj sa klasičnim P/Invoke-om u C# (jer u većini slučajeva nije potreban marshalling, a negde čak nisu potrebne ni sigurnosne provere pri takvim pozivima).
---
Sve u svemu, samo hoću da kažem da je sve to moguće, vrlo elegantno rešivo i odlično radi, ali ne treba koristiti napamet već samo treba biti svestan barem malo šta se ispod zapravo dešava.
[Ovu poruku je menjao Goran Arandjelovic dana 29.08.2009. u 16:00 GMT+1]