Newsgroup: it.comp.programmare.win32
Titolo: (ATL) (COM) (VC++) Istanza globale

Salve a tutti.
ho sviluppato una libreria DLL COM con VC++ e il framework. Non ho avuto
grossi problemi, ma vorrei migliorarne un aspetto.
Ho una classe "Factory", e vorrei che i suoi metodi siano accessibili da VB
senza dover istanziare esplicitemente un oggetto di questo tipo. Per la
cronaca, quando si crea una DLL COM con vB questa cosa si ottine molto
facilmente specificando l'attributo GlobalInstance sulla classe in
questione. Con VC++... boh? qualcuno ne sa qualcosa?
grazie
  Giovanni

 senza dover istanziare esplicitemente un oggetto di questo tipo.
Io non so nulla di COM, ATL e simili mostri di acronimia, ma hai provato a
dichiarare i metodi interessati "static" ?
Massimo

 ha scritto nel messaggio
news:90rb0n$to$1...@news.mclink.it...

no, ma non credo che questa sia la soluzione. comunque ci provo, grazie.

Prova a rendere export nel file .def della libreria la funzione API del COM
ma PUBLIC

> Salve a tutti.

Devi utilizzare le librerie dei tipi. In Visual Basic e Visual J++
viene creata automaticamente. Per questo motivo un componente
generato con questi IDE possiede la facolta' di esportare la sua
interfaccia in modo semplice e trasparente.
Per creare le librerie dei tipi ci sono le interfaccie COM+ ICreateTypeLib()
e ICreateTypeInfo, mentre per leggerle ci sono ITypeLib() e ITypeInfo().
La cosa e' molto piu' semplice di quanto si immagini. Sfruttando il
compilatore MIDL basta apportare delle semplici modifiche al tuo IDL
per far generare una libreria dei tipi (.tlb). Es:
import "unknwn.idl";
[ object, uuid(10000001-0000-0000-0000-000000000001) ]
interface IMyInterface : IUnknown
{
    HRESULT MyFunc(int x, int y, int z, [out, retval] int* retval);
}
[ uuid(10000003-0000-0000-0000-000000000001),
  helpstring("My COM+ Component Type Library"),
  version(1.0) ]
library Component
{
    importlib("stdole32.tlb");
    interface IMyInterface;
    [ uuid(10000002-0000-0000-0000-000000000001) ]
    coclass MyCOM
    {
        interface IMyInterface;
    }
};
Il trucco e' la parola chiave "library" nel file IDL. Questa
specifica al MIDL di generare la libreria dei tipi secondo quanto
contenuto nella definizione "library Component". Il file stdole32.tlb
e' l'implementazione di interfaccia standard di Microsoft per la
creazione delle librerie dei tipi. All'interno include le definizioni
di IUnknown, IDispatch, IEnumVARIANT (proprio quest'ultimo e'
esplicitamente progettato per Visual Basic e Visual J++).
Per non lasciare la libreria dei tipi esternamente al componente e'
possibile incorporarla elegantemente come risorsa!! Il procedimento
e' semplicissimo. Basta aggiungere nel file di risorse (.rc) del
componente:
TYPELIB "mycomponent.tlb"
dove ovviamente mycomponent e' il nome del libreria dei tipi del tuo
componente (che viene creata pochi istanti prima dal MIDL ;).
Veniamo ora alla parte piu' pallosa, la registrazione della libreria
dei tipi. Tutte le informazioni delle librerie dei tipi vengono inserite
nel registro di sistema sotto la chiave HKEY_CLASSES_ROOT\TypeLib.
L'identificatore di ciascuna libreria e' un normalissimo GUID. All'interno
sono contenute varie informazioni come la versione, il percorso della
libreria, un percorso alternativo e altro ancora. Farlo a mano e'
una palla tremenda quindi conviene sfruttare la registrazione automatica
del componente inserendo all'interno tutte le informazioni necessarie.
Per far cio' ci vengono incontro la funzione LoadTypeLibEx() e
RegisterTypeLib() che creano automaticamente tutte le voci necessarie
nella chiave del registro TypeLib e ogni interfaccia compatibile con
l'automazione definita nella libreria dei tipi (noi siamo tranquilli
visto che la nostra e' derivara dalla standard!). Le interfaccie vengono
registrate in HKEY_CLASSES_ROOT\Interface, per la cronaca. ;)
Utile risulta anche la funzione UnRegisterTypeLib() che viene chiamata
di solito quando si disistalla un componente o nei componenti in-process
richiamando la funzione DllUnregisterServer.
Veniamo ora al sodo. Qui sotto e' riportato il codice per la registraione
e rimozione del componente:
HRESULT __stdcall DllRegisterServer()
{
    // Recupera il percorso del componente
    char DllPath[MAX_PATH];
    GetModuleFileName(g_hInstance, DllPath, sizeof(DllPath));
    // Converto il path in UNICODE
    OLECHAR wDllPath[MAX_PATH];
    mbstowcs(wDllPath, DllPath, sizeof(wDllPath));
    // ...e finalmente registro la libreria dei tipi
    ITypeLib* pTypeLib;
    HRESULT hr =
        LoadTypeLibEx(wDllPath, REGKIND_REGISTER, &pTypeLib);
    if(FAILED(hr))
        return hr;
    pTypeLib->Release();
    return RegisterServerEx(g_regData, DllPath);
}
HRESULT __stdcall DllUnregisterServer()
{
    // Rimuovo la libreria dei tipi.
    UnRegisterTypeLib(LIBID_Component, 1, 0,
        LANG_NEUTRAL, SYS_WIN32);
    return UnregisterServerEx(g_regData);
}
A beneficiare di questa implementazione non e' solo VB o VJ ma
anche VC++. Es:
#define _WIN32_DCOM
#import "mycomponent.dll" no_namespace
#include <iostream.h>
void main()
{
    CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
    IMyInterfacePtr myRef(__uuidof(MyCOM));
    int result = myRef->MyFunc(5, 13, 17);
    cout << "Vector = " << result << endl;
    myRef = NULL;
    CoUninitialize();
}
Siamo giunti al termine del tutorial! Alla prossima...
Ciao,
Il Michett@
--
p.s. la fattura dove la spedisco? :^)

 ha scritto nel messaggio
news:90vmug$d86$1...@pluto.sm.dsi.unimi.it...


Ehm...nella fretta di postare (le donne a volte rompono!) mi sono
scordato di completare il discorso sull'istanza globale della coclasse
in stile VB (praticamente mi sono scordato di dire la cosa piu'
importante :). Riporto quando gia' inviato a Giovanni via e-mail:
[cut]
Veniamo dunque allo specifico del tuo caso. L'ATL Object Wizard durante
la creazione degli oggetti genera gia' le informazioni necesarie per creare
la libreria dei tipi (type library) quindi ci risparmia un bel po' di
lavoro.
Le uniche modifiche manuali che occorre apportare per trasformare una
coclasse come SINGLETON sono a livello del file IDL e nella classe.
Nel primo bisogna inserire nella dichiarazione della coclasse il TAG
[appobject], che identifica la classe come una "application wide global
class" :
[...]
[
      uuid(AF839C47-4772-485E-AF1F-0DFC9693991A),
      helpstring("MyCOM Class"), appobject
   ]
   coclass MyCOM
   {
      [default] interface IMyInterface;
   };
};
[...]
Ora non resta che inserire la macro DECLARE_CLASSFACTORY_SINGLETON(myclass)
nella definizione della stessa :
////////////////////////////////////////////////////////////////////////////
/
// CMyCOM
class ATL_NO_VTABLE CMyCOM :
   public CComObjectRootEx<CComSingleThreadModel>,
   public CComCoClass<CMyCOM, &CLSID_MyCOM>,
   public IDispatchImpl<IMyInterface, &IID_IMyInterface, &LIBID_TESTATLLib>
{
public:
   DECLARE_CLASSFACTORY_SINGLETON(CMyCOM)
   CInsideCOM()
   {
   }
[...]
Compila e testa su VB. Basta aggiungere ai riferimenti la nostra library
e bingo. Possiamo visualizzare direttamente i metodi e proprieta' senza
istanziare nessun oggetto.
Il mio consiglio e' comunque di non abusare di questa tecnica (e'
sconsigliata) in quanto i SINGLETON non sono supportati nel run-time di
COM+ e mi sembra di aver letto da qualche parte che fanno casini con
il supporto COM+ di .NET (non ne sono sicurissimo, ma visto che non
sono supportati in run-time c'era d'aspettarselo).
Ciao,
Il Michett@
--

grazie mille per le informazioni! (vabé, ti ho già ringraziato in privato,
ma non volevo sembrare maleducato sul NG :D)