2010-05-27 18 views
6

Sono davvero confuso dalla moltitudine di informazioni errate sull'interoperabilità nativa/gestita.Chiamata di un callback nativo dal codice gestito .NET (durante il caricamento del codice gestito tramite COM)

Ho un normale exe C++ che NON è compilato utilizzando roba CLR (non è né gestito C++ né C++/CLI e non lo sarà mai). Questo exe C++ è "responsabile", non esiste un wrapper gestito per questo.

Vorrei accedere ad un codice che ho in un assembly C# dal mio exe C++. Posso accedere all'assembly C# dal mio codice C++ usando COM. Tuttavia, quando il mio codice C# rileva un evento mi piacerebbe richiamarlo nel mio codice C++. Il puntatore della funzione C++ da richiamare verrà fornito in fase di runtime. Si noti che il puntatore della funzione C++ si riferisce a una funzione trovata nell'ambiente di esecuzione di exe. Può usare membri statici da lì. Non voglio che il codice gestito provi a caricare qualche DLL per chiamare una funzione (non ci sono DLL).

Come faccio a passare questo puntatore di funzione C++ al mio codice C# tramite COM/.NET e il mio codice C# lo chiama correttamente?

Grazie!

risposta

6

Probabilmente desidera utilizzare Marshal.GetDelegateForFunctionPointer:

  1. Creare un tipo delegato che corrisponde la firma della funzione nativa, tenendo presente il modo giusto per il marshalling tipi e usando MarshalAs come necessario
  2. Comunicare il puntatore della funzione nativa dal codice nativo al codice C# tuttavia (nel tuo caso sembra che tu possa utilizzare la tua connessione COM -> C#)
  3. Utilizzare Marshal.GetDelegateForFunctionPointer per trasformare il puntatore in un delegato richiamabile C#
  4. Richiamare il delegato con i parametri

Junfeng Zhang ha un esempio di fare questo here.

Nota le restrizioni di cui su MSDN:

Il metodo GetDelegateForFunctionPointer ha le seguenti limitazioni:

  • Generics non sono supportati in Interop scenari.
  • Non è possibile passare una puntina non valida con il metodo a questo metodo.
  • È possibile utilizzare questo metodo solo per i puntatori di funzione non gestiti non gestiti.
  • Non è possibile utilizzare questo metodo con i puntatori di funzione ottenuti tramite C++ o dal metodo GetFunctionPointer.
  • Non è possibile utilizzare questo metodo per creare un delegato da un puntatore alla funzione un altro delegato gestito.

La parte su C++ è probabilmente riferendosi a puntatori a funzione per metodi di classe. Questo dovrebbe ancora funzionare per le funzioni globali.

+0

Nel passaggio 2 il puntatore di funzione inizialmente arriverà in C# -land come IntPtr? – evilfred

+1

Per ottenere il puntatore da C/C++ a C#, verrà eseguito il marshalling. Sì, i puntatori C/C++ sono rappresentati come C# 'IntPtr', le cui dimensioni sono specifiche della piattaforma. –

+0

Probabilmente sto facendo qualcosa di stupido. Il compilatore C++ si lamenta di non poter convertire il mio parametro da voic (__ cdecl *) (UINT) a long (il metodo accetta un IntPtr in C#). Inoltre, l'esempio di Zhang riguarda un puntatore di funzione C++ recuperato in C# non recuperato da C++ ... – evilfred

4

L'approccio COM standard è la sottoscrizione di un evento generato dal server COM. L'utilizzo può utilizzare la parola chiave evento in C#, l'interoperabilità CLR implementa automaticamente la colla COM necessaria. Usa l'interfaccia IConnectionPoint nel tuo codice C++. Backgrounder is here.

Problemi correlati