[ Zevs85 @ 28.08.2009. 11:28 ] @
Kakva su vasa iskustva sa ovim?

Da li je moguce u ANSI c++ kodu pozvati CLI funkciju koja vraca npr System::String i prekonvertovati u std::string...? Ili tako nesto.
[ Goran Arandjelovic @ 29.08.2009. 13:26 ] @
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]
[ Zevs85 @ 31.08.2009. 14:34 ] @
Odlicno. Hvala.
Sad sam napravio par primera i mislim da mi je prilicno jasno ;)