2012-10-24 10 views
11

questa è probabilmente una domanda COM di noob, ma su Google questo solleva più domande che fornire risposte:È sicuro utilizzare C++ "operator new" piuttosto che CoCreateinstance per creare un oggetto COM?

È sicuro utilizzare "operatore nuovo" invece di CoCreateInstance per un'istanza COM locale?

quello che ho fatto:

  1. ho implementato l'interfaccia IOperationsProgressDialog http://msdn.microsoft.com/en-us/library/windows/desktop/bb775368(v=vs.85).aspx utilizzando ereditarietà pubblica e quindi anche implementato l'interfaccia IUnknown.

  2. Ho creato un'istanza tramite "nuovo RecyclerProgressCallback" e l'ho inserita in un COM-Ptr per la gestione della vita. "RecyclerProgressCallback" è il nome della mia classe derivata.

  3. Sto usando questo esempio nel IFileOperation :: SetProgressDialog http://msdn.microsoft.com/en-us/library/windows/desktop/bb775803(v=vs.85).aspx

Riassunto: Il mio approccio "sembra" funzionare, ma non mi fido, non c'è informazioni davvero troppo sconcertante intorno Creazione di oggetti COM per fare affidamento solo sul comportamento osservabile.

Ci sono dei rischi sottili, errori o altri problemi? Grazie!

risposta

5

Li ho persino messi in pila. La risposta di Andrey (ora cancellata) ha erroneamente suggerito che non è sicuro, perché si ignora il conteggio dei riferimenti COM. Questo è un ragionamento errato. COM non conta i riferimenti; ti delega la responsabilità. Devi chiamare delete o free(), o qualsiasi altra cosa usi la tua lingua, dopo che COM chiama il tuo metodo Release nella sua ultima interfaccia. La parola importante è dopo il. Non quando, perché non sei obbligato a farlo immediatamente.

Analogamente, CoCreateInstance è una deviazione lunga perché COM è indipendente dalla lingua e non sa se un oggetto deve essere creato con malloc o new. È così, basta ignorare l'intera logica COM.

+0

> basta ignorare l'intera logica COM. Questo era quello che speravo di sentire! Andando alla lettura lunga, la registrazione di nuovi oggetti COM non sarebbe stata solo dolorosa in Visual C++ Express, ma avrebbe anche danneggiato la mia applicazione in modo "portatile". – Zenju

+0

Bene, devi ancora implementare correttamente 'IUnknown' dato che fa parte dell'interfaccia' IOperationsProgressDialog' che stai promettendo. Per esempio. il tuo 'IOperationsProgressDialog :: QueryInterface (IID_IUnknown)' deve avere successo ecc. – MSalters

+0

Sì, l'ho fatto. È buono IUnknown è una classe base astratta, quindi ho notato gli errori del compilatore solo dopo aver implementato IOperationsProgressDialog. Quindi, l'intera procedura è solo ordinaria implementazione di funzioni virtuali in C++ ... questo è stato più semplice di quanto mi aspettassi da COM, il che mi rende sospetto. – Zenju

1

Dipende da cosa esattamente si sta creando. Quando si suppone che fornisca un puntatore COM nessuno ti chiede se è istanziato con COM API, o new, oppure a volte può essere anche oggetto su stack (a patto che tu riesca a garantire che non venga distrutto nello stack prima che tutti i riferimenti vengano rilasciati).

Quindi la risposta è sì, è possibile utilizzare new e andrebbe bene. Tuttavia, dovrebbe comunque essere un'interfaccia COM valida, dovrebbe implementare il conteggio dei riferimenti e QueryInterface come gli oggetti COM.

0

Questo funzionerà correttamente. Questo è il modo in cui un server COM tipicamente crea i suoi oggetti internamente (almeno uno scritto in C++). Dal tuo punto di vista, la classe RecyclerProgressCallback è solo un codice C++. Puoi trattarlo come qualsiasi altra classe del tuo programma.

Detto questo, COM è un campo minato di trucchi sottili. Non posso promettere che non incontrerai problemi con la tua classe, ma posso assicurarti che tali problemi non saranno correlati al tuo utilizzo dell'operatore new.

1

CoCreateInstance API esaminerà la registry trovare il modulo con parametro specificato CLSID, caricarlo e attraverso un meccanismo (Dipende se il codice è DLL o EXE) chiamerà alcune funzioni per creare l'oggetto. Quindi per il tuo codice per far funzionare CoCreateInstance, dovresti scrivere una classe che implementa l'interfaccia IClassFactory di COM e registrarla nel registro e poi chiamare CoCreateInstance che fa un paio di lavori extra con il tuo codice per fare almeno il tuo adorabile operator new , quindi sì certo che è sicuro. In generale è sempre sicuro chiamare operator new dell'implementazione delle interfacce source (interfacce dichiarate solo per callback) nel codice e anche questo è il modo preferito.

-1

Generalmente non è sicuro, non solo per il conteggio dei riferimenti ma anche per il marshalling: la classe può avere un modello di threading che richiede il marshalling. CoCreateInstance creerà un proxy e uno stub se questo è il caso, mentre lo new no.

+0

Questo non è vero. Esaminerete l'interfaccia e l'oggetto COM e verrebbero sottoposti a marshalling da COM nello stesso modo sicuro. –

+0

No. Se la classe richiede il marshalling, ciò che ottieni da CoCreateInstance è un oggetto proxy, non l'oggetto stesso. Questo non accadrà mai con 'new'. – user1610015

+1

Stai rendendo le cose disordinate senza motivo. Se il chiamante ha bisogno di una lezione su un altro appartamento, egli '' nuovo' da un altro thread e lascia che COM esegua il normale marshalling. 100% sicuro e praticabile. Se il chiamante ha bisogno di 'new' per una ragione e si occupa di threading,' new' è assolutamente sicuro e affidabile. –

Problemi correlati