Newsgroup: it.comp.programmare.win32
Titolo: Collection e Typename

Vorrei scrivermi la mia DLL COM per potere avere finalmente una
collection che abbia il controllo dei tipi, cioe' sei decido che una
mia QColelction deve essere di soli tipi Papero, se run-time provo a
caricare un oggetto a run-time di tipo Cane mi deve dare un errore. A
design time sarebbe meglio, pero' non si puo' avere tutto.
Il mio problema e' sapere l'ID univoco di un oggetto passato come
parametro, praticamente vorrei sapere cosa fa il VB su questa
istruzione:
Typename(mioOggetto)
Ho guardato su MSDN, ma non mi e' per niente chiaro come procedere, e
quale interfaccia richiedere.
--
Tieni per te il Papero se vuoi la mia email
Sito Papero -> 
http://utenti.tripod.it/papero

 quale interfaccia richiedere.
Se per qualche ragione vuoi comunque ricevere un VARIANT, e curare
tu stesso la trasformazione (verificando che essa sia possibile...) ad un
certo tipo, l'operazione canonica e`:
    HRESULT GiveMeADuck(VARIANT* pVar, IDuck* *pDuck) {
        // un controllo in piu` non fa mai male
        if(!pVar || !pDuck) return E_POINTER;
        *pDuck = 0;    // buona abitudine: azzerare gli [out]...
 
        // l'oggetto passato deve essere un oggetto COM...:
        HRESULT hr = VariantChangeType(pVar, pVar, 0, VT_UNKNOWN);
        if(FAILED(hr)) return hr;
        if(!pVar->punkVal) return S_FALSE;    // caso "Nothing"
        // ...e deve accettare il QueryInterface che vogliamo noi
        return pVar->punkVal->QueryInterface(pDuck);
    }
Qui sto usando la comodissima e benedetta versione member-template
di QueryInterface definita dalle versioni recenti dell'SDK, cioe`, nell'header
file di sistema Unknwn.h,
#if (_MSC_VER >= 1200) // VC6 or greater
  template <class Q>
  HRESULT STDMETHODCALLTYPE QueryInterface(Q** pp)
  {
   return QueryInterface(__uuidof(Q), (void**)pp);
  }
#endif    
Se per qualche ragione devi scrivere i tuoi sorgenti per una versione
piu` antica di SDK e/o C++, dovrai naturalmente ricorrere ai soliti
antichi e dannati cast, cioe` cambiare l'ultima riga con, ad esempio:
        return pVar->punkVal->QueryInterface(IID_IDuck, (void**)pDuck);
Comunque, a parte la comodita` e l'eleganza, la semantica non cambia.
Data una qualsiasi VARIANT v, comunque, l'equivalente di Typename(v)
puoi ottenerlo esaminando v.vt.  Se il tipo e` VT_UNKNOWN ovvero
VT_DISPATCH, e il puntatore non e` nullo, ci sono vari approcci per
tentare di risalire a run-time al "vero tipo dell'oggetto" (quale VB usi,
dipende dal release di VB, e penso anche dalla sua Edition...).
Alcuni oggetti (tipicamente controlli Active/X, anche se qualunque oggetto
puo` scegliere di farlo) implementano IProvideClassInfo o IProvideClassInfo2.
Questa ha un metodo GetClassInfo che ti ritorna la ITypeInfo* per la
coclass dell'oggetto.
ITypeInfo ti permette di ricavare molte informazioni sul tipo di un oggetto;
in particolare, la sua GetDocumentation, chiamata con primo argomento
pari a MEMBERID_NIL, ti torna il nome della coclass e la sua helpstring.
In mancanza di IProvideClassInfo, hai ancora una chance se puoi ottenere
l'IDispatch dell'oggetto (tipicamente con una VariantChangeType per
VT_DISPATCH, ma puoi anche, alternativamente, scegliere di fare tu
stesso la QueryInterface).
Fra le funzioni di IDispatch trovi GetTypeInfoCount, che torna 0 se
l'oggetto non fornisce type-information, 1 se si`; se si`, allora con
GetTypeInfo puoi ottenere l'ITypeInfo, da usare come sopra.  In
questo caso, pero`, non avrai i dati della *coclass*, bensi` quelli
della *interfaccia* (normalmente duale) il cui IDispatch hai usato.
Ho scritto una piccola libreria, AU.Dll, che contiene vari oggetti COM
di AUsilio per la gestione di AUtomation (e, come dice il nome, vale
tant'oro quanto pesa -- mica tanto, visto che sono meno di 100k:-).
La classe CBrowser, contenuta in questa libreria, esemplifica in modo
abbastanza utile la "caccia alle informazioni" relative a un dato oggetto
COM.  Con oltre 1200 righe di codice, CBrowser rappresenta oltre 1/4
dei sorgenti della intera AU.Dll.
Se c'e` interesse, potrei cercare di ottenere il permesso di rilasciare
questa piccola libreria come Open-Source (l'ho sviluppata al lavoro e
come parte del mio lavoro, quindi non posso prendere l'iniziativa di
rilasciarla in nessuna forma senza questo permesso; da cui, questo
tentativo di verifica dell'interesse in merito -- se serve solo a una o
due persone, non mi metto neanche a cercare di ottenere il permesso,
ma se l'interesse fosse diffuso, allora potrebbe valerne la pena).
Alex

Alex
Ti ringrazio per la lunga replica e per la pazienza.
Il tutto e' nato da una discussione con un collega. Da quella
discussione ho creato un add-in per avere degli assert come e meglio
che in C. Open Source perche' lo sviluppato nel mio tempo libero,
anche se la carta stampata del MSDN la messa la ditta. 
Ora non so come facevo senza. 
Adesso forrei fare il secondo passo per migliorarmi la mia esistenza.
Per esempio mi sono costruito strutture dati + codice per gestirmi
certe cose (per esempio per avere vettori multipli di ordinamento). Il
problema e' che mi fa schifo dovere riscrivere il codice perche' nel
progetto B la struttura dati e' cambiata. Io voglio potere tipizzare
il mio codice a run-time, e questo senza dovere riscrivere una sola
riga di codice. 
Vorrei insomma i template in VB, ma quelli non ci saranno mai perche'
il target e' diverso. La domanda e' pero', e' possibile un accrocchio
che mi porti a risultati simili?
++++
Sempre a spese delle ditta mi sono stampato il tutorial su COM
disponibile su 
http://www.develop.com/learncom.htm
 (comode le mail
list della Microsoft !!). Conosco solo Don Box, pero' come nome mi
sembra una garanzia. Nel mio tempo libero lo leggero', e spero che mi
sia di aiuto.
++++
Intanto ho fatto scorta di barrette di cioccolato nocciolato. Alimento
ritengo fondamentale per chiunque pretenda di affrontare COM.


 A me interesserebbe. Un Papero un voto, mi sembra che si dica cosi'.
Vediamo se e` interessato anche qualcun altro.
Alex