2013-05-13 10 views
6

Konwertuję zarządzaną metodę System.Action na niezarządzaną funkcję std :: wewnątrz projektu C++/CLI; powinienem zwolnić dany IntPtr po użyciu wywołania zwrotnego, czy jest to niepotrzebne?Marshal :: GetFunctionPointerForDelegate: czy powinienem zwolnić jego wynik?

void MyClass::Execute(System::Action^ callback) 
{   

    IntPtr callbackPtr = Marshal::GetFunctionPointerForDelegate(callback); 
    std::function<void (void)> nativeCallback = static_cast<void (__stdcall *) (void)>(callbackPtr.ToPointer()); 

    m_nativeObject->Execute(wrappedCallback); 

    // should I release callbackPtr here? 
} 

Odpowiedz

6

No. Nie ma Marszałek klasy metoda, aby to zrobić. Podobnie jak cały kod generowany dynamicznie, thunk, który jest tworzony przez tę metodę, jest powiązany z AppDomain i zostaje rozładowany po wyładowaniu AppDomain.

Należy zauważyć, że tak nie jest w przypadku obiektu uczestnika, podlega on normalnym zasadom zbierania śmieci. I musisz być ostrożny, thunk ma nie utrzymać go przy życiu. Co jest błędem w twoim kodzie, delegata można zbierać podczas wykonywania natywnego kodu. musisz dodać poniższy wiersz kodu do końca metody:

GC::KeepAlive(callback); 

Przy założeniu, że zwrotna zostanie wykonana tylko tak długo, jak metoda execute() jest wykonywany. Jeśli kod niezarządzany przechowuje wskaźnik funkcji poza tym wywołaniem metody, musisz gdzieś przechowywać obiekt delegata, aby zachować jego ważność.

+0

nawet jeśli m_nativeObject-> Execute (wrappedCallback) jest synchroniczny? – Notoriousxl

+5

Wątek zrujnuje ci dzień. Cóż, tydzień. –

2

Nie trzeba zwolnić wskaźnika. Masz już wskaźnik do funkcji (jest to rozmiar 32/64 bitów w zależności od architektury komputera). Jeśli infrastruktura ramek .net wymagała czegoś więcej, aby uruchomić wskaźnik, byłaby taka sama dla wszystkich metod, więc byłaby przydzielona statycznie (bez stanu).

Powiązane problemy