2013-05-13 1 views
6

Sto convertendo un System.Ation gestito in una funzione std :: non gestita all'interno di un progetto C++/CLI; dovrei rilasciare il dato IntPtr dopo aver usato il callback, o non è necessario?Marshal :: GetFunctionPointerForDelegate: dovrei rilasciare il suo risultato?

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? 
} 

risposta

6

No. Non esiste un metodo di classe maresciallo per fare questo. Come tutto il codice generato dinamicamente, il thunk creato con questo metodo è associato a AppDomain e viene scaricato quando AppDomain viene scaricato.

Si noti che questo non è il caso per l'oggetto delegato, è soggetto alle normali regole di garbage collection. E devi stare attento, il thunk fa non tenerlo in vita. Che è un bug nel codice, il delegato può essere raccolto mentre il codice nativo è in esecuzione. Avrete bisogno di aggiungere questa riga di codice alla fine del metodo:

GC::KeepAlive(callback); 

con il presupposto che il callback sarà effettuato solo fino a quando il metodo execute() è in esecuzione. Se il codice non gestito memorizza il puntatore della funzione oltre questa chiamata al metodo, è necessario memorizzare l'oggetto delegato da qualche parte per mantenerlo valido.

+0

anche se m_nativeObject-> Execute (wrappedCallback) è sincrono? – Notoriousxl

+5

Una discussione ti rovinerà la giornata. Bene, settimana. –

2

Non è necessario rilasciare il puntatore. Hai già il puntatore alla funzione (che è una dimensione 32/64 bit a seconda dell'architettura della tua macchina). Se l'infrastruttura della rete .net avesse bisogno di qualcosa in più per eseguire il puntatore, sarebbe la stessa per tutti i metodi, quindi sarebbe allocata staticamente (nessuno stato).