Component Object Model (COM) by UUzgpZav

VIEWS: 27 PAGES: 25

									Component Object Model
       (COM)
                       Cos’è COM?
• Tecnologia specifica della famiglia di sistemi operativi Windows che
  abilita la comunicazione fra i componenti software del sistema
• Teconologia component-based
    – Favorisce lo sviluppo di componenti riusabili
    – Permette di creare applicazioni connettendo fra loro inisiemi di
      componenti
    – Rende possibile l’uso e lo sviluppo di servizi


• Si tratta di una famiglia di tecnologie che include
    – COM+
    – DCOM
    – ActiveX
                Brevi cenni storici
• 1991: OLE (Object Linking and Embedding)
   – Basato su DDE (dynamic data exchange)
   – Dedicato principalmente al progetto di compound-documents
     (documenti costituiti di parti gestite da diverse applicazioni)
• 1993: OLE2
   – COM viene introdotta come tecnologia di riferimento
   – Dedicato al progetto di componenti applicativi in genere
• 1994: OCX (OLE Control Extension)
   – Estensioni COM per la creazione di componenti nella maggior parte dei
     linguaggi di programmazione
• 1996: ActiveX
   – Estensione dei componenti OCX
   – Possono essere contenuti in pagine Web ed eseguiti nel browser
• 1996: DCOM (distributed COM)
• …
• Oggi: .NET
  COM: Principali caratteristiche
• Standard binario per l’invocazione di funzioni fra diversi
  componenti
   – Indipendenza dal linguaggio di programmazione
   – Interoperabilità fra componenti di diversi fornitori
   – Meccanismi di scoperta delle interfacce implementate dai
     componenti
   – Meccanismo per l’identificazione univoca dei componenti e delle
     interfacce
• Permette trasparentemente la comunicazione fra
  componenti eseguiti nello stesso processo o in processi
  diversi
• Disponibile su diverse piattaforme
   – Windows, Macintosh, Unix…
                     Binary Standard
•   Oggetti COM: elementi di codice eseguibile che forniscono servizi al resto
    del sistema
    (terminologia alternativa: componenti, component object)
•   Il lay-out in memoria delle funzioni eseguibili è definito in modo standard per
    permettere l’interoperabilità binaria
•   Una virtual table contiene i puntatori all’implementazione delle funzioni
•   La doppia indirettezza permette a multiple istanze di condividere la stessa
    virtual table
                           Interfacce
• I componenti COM forniscono i propri servizi attraverso collezioni di
  funzioni dette interfacce
• Un componente generalmente supporta un insieme di interfacce
• Convenzionalmente il nome delle interfacce comincia con una I (i
  maiuscola) seguita da un ulteriore lettera maiuscola
    –   IUnknown (supportata da tutti i componenti COM)
    –   ILookup
    –   IDropTarget
    –   IDragSource
    –   IUnEsempioDiInterfaccia

• Un puntatore ad un componente COM è in effetti un puntatore ad
  un’interfaccia supportata dal componente
    – Es: IUnknown* pRef;
Notazione grafica per i
  componenti COM
                                                componente




Interfaccia implementata/supportata/esportata
           Caratteristiche generali
              delle interfacce
• Un’interfaccia non è una classe
   – Solo metodi senza implementazione
• Le interfacce non sono componenti
   – Piuttosto vengono implementate/supportate/esportate dai
     componenti
• Gli utilizzatori di un componente usano puntatori a
  interfacce (supportate dal componente)
• I componenti COM possono implementare interfacce
  multiple
• Le interfacce sono fortemente tipizzate
• Le interfacce sono immutabili
                             GUID
• COM garantisce l’identificazione univoca di interfacce e
  classi attraverso GUID
   – GUID = Globally Unique Identifier
   – Numeri di 128 bit
   – Ogni GUID è garantito come unico nel mondo senza limiti di
     spazio e tempo
   – L’identificatore GUID di un interfaccia è detto IID
   – L’identificatore GUID di una classe è detto CLSID
   – I nomi simbolici sono usati solo per convenienza, ma
     l’identificazione reale di classi e interfacce avviene attraverso
     GUID
• Esempio di GUID
   DEFINE_GUID(IID_ILOOKUP, 0xc4910d71, 0xba7d, 0x11cd,
     0x94, 0xe8, 0x08, 0x00, 0x17, 0x01, 0xa8, 0xa3);
                  Tool GuidGen
• Tool distribuito con Windows SDK
    Component Object Library
• Parte del sistema operativo con cui si
  interagisce per gestire COM
• Contiene le API principali per la creazione e la
  gestione dei componenti COM
• Alcune API della COM library sono
  – HRESULT CoInitialize(LPVOID pvReserved);
      • Inizializzazione dell’ambiente di esecuzione COM
  – void CoUninitialize(void);
      • Chiusura della COM library e delle connessioni COM per il
        thread corrente
                   CoCreateInstance
                    (COM Library)
• HRESULT CoCreateInstance(
        REFCLSID rclsid,
        LPUNKNOWN pUnkOuter,
        DWORD dwClsContext,
        REFIID riid,
        LPVOID* ppv);
• rclsid
    – CLSID della CoClass che implementa il componente
• pUnkOuter
    – Serve per l’aggregazione di componenti. Per adesso useremo NULL
• dwClsContext
    – Tipo di server COM da usare (in-process, local, remote): per ora
      useremo CLSCTX_INPROC_SERVER
• riid
    – IID dell’interfaccia per usare il componente
• ppv
    – Puntatore all’interfaccia restituito come risultato di CoCreateIntance
                   Un esempio
• Il componente di sistema ActiveDesktop esporta i propri
  servizi attraverso l’interfaccia IActiveDesktop
• IID_IActiveDesktop
   – f490eb00-1240-11d1-9888-006097deacf9
• CLSID_ActiveDesktop
   – 75048700-ef1f-11d0-9888-006097deacf9
               IActiveDesktop (shlobj.h)
DECLARE_INTERFACE_( IActiveDesktop, IUnknown ) {
  // IUnknown methods
  STDMETHOD (QueryInterface)(THIS_ REFIID riid, void **ppv) PURE;
  STDMETHOD_(ULONG, AddRef) ( THIS ) PURE;
  STDMETHOD_(ULONG, Release) ( THIS ) PURE;

     // IActiveDesktop methods
     STDMETHOD (ApplyChanges)(THIS_ DWORD dwFlags) PURE;
     STDMETHOD (GetWallpaper)(THIS_ LPWSTR pwszWallpaper, UINT cchWallpaper, DWORD dwReserved)
         PURE;
     STDMETHOD (SetWallpaper)(THIS_ LPCWSTR pwszWallpaper, DWORD dwReserved) PURE;
     STDMETHOD (GetWallpaperOptions)(THIS_ LPWALLPAPEROPT pwpo, DWORD dwReserved) PURE;
     STDMETHOD (SetWallpaperOptions)(THIS_ LPCWALLPAPEROPT pwpo, DWORD dwReserved) PURE;
     STDMETHOD (GetPattern)(THIS_ LPWSTR pwszPattern, UINT cchPattern, DWORD dwReserved) PURE;
     STDMETHOD (SetPattern)(THIS_ LPCWSTR pwszPattern, DWORD dwReserved) PURE;
     STDMETHOD (GetDesktopItemOptions)(THIS_ LPCOMPONENTSOPT pco, DWORD dwReserved) PURE;
     STDMETHOD (SetDesktopItemOptions)(THIS_ LPCCOMPONENTSOPT pco, DWORD dwReserved) PURE;
     STDMETHOD (AddDesktopItem)(THIS_ LPCCOMPONENT pcomp, DWORD dwReserved) PURE;
     STDMETHOD (AddDesktopItemWithUI)(THIS_ HWND hwnd, LPCOMPONENT pcomp, DWORD dwReserved)
         PURE;
     STDMETHOD (ModifyDesktopItem)(THIS_ LPCCOMPONENT pcomp, DWORD dwFlags) PURE;
     STDMETHOD (RemoveDesktopItem)(THIS_ LPCCOMPONENT pcomp, DWORD dwReserved) PURE;
     STDMETHOD (GetDesktopItemCount)(THIS_ LPINT lpiCount, DWORD dwReserved) PURE;
     STDMETHOD (GetDesktopItem)(THIS_ int nComponent, LPCOMPONENT pcomp, DWORD dwReserved) PURE;
     STDMETHOD (GetDesktopItemByID)(THIS_ ULONG_PTR dwID, LPCOMPONENT pcomp, DWORD dwReserved)
         PURE;
     STDMETHOD (GenerateDesktopItemHtml)(THIS_ LPCWSTR pwszFileName, LPCOMPONENT pcomp, DWORD
         dwReserved) PURE;
     STDMETHOD (AddUrl)(THIS_ HWND hwnd, LPCWSTR pszSource, LPCOMPONENT pcomp, DWORD dwFlags)
         PURE;
     STDMETHOD (GetDesktopItemBySource)(THIS_ LPCWSTR pwszSource, LPCOMPONENT pcomp, DWORD
         dwReserved) PURE;
};
             Uso del componente
               ActiveDesktop
#include <shlobj.h>
……
HRESULT hr;
IActiveDesktop* pIAD;

// creazione del componente
hr = CoCreateInstance(CLSID_ActiveDesktop,
    NULL,
    CLSCTX_INPROC_SERVER,
    IID_IActiveDesktop,
    (void**)&pIAD );

// uso del componente
hr = pIAD->GetWallpaper(wszPath, MAX_PATH, 0);
                            HRESULT
• Handle di un risultato in COM
• Valore di 32 bit che segnala il risultato di un operazione
    – Usato dalle API della COM Library
    – Usato dai metodi delle interfacce COM
• Si interpreta attraverso macro per scoprire il successo/fallimento
    – SUCCEEDED(hr)
        • Fa il check che il valore sia >=0
    – FAILED(hr)
        • Fa il check che il valore sia <0
• I valori specifici HRESULT danno informazioni sugli errori, e sono
  associati a corrispondenti messaggi testuali. Esempi:
    – E_NOINTERFACE (0x80004002) “No such interface supported.”
    – CO_E_CREATEPROCESS_FAILURE (0x80004018): “The server
      process could not be started. The pathname may be incorrect.”
    – CO_E_NOTINITIALIZED (0x800401F0) - “CoInitialize has not been
      called.”
          Error Lookup Tool
• Parte di Visual Studio
           Nota Tecnica:
  Unicode String e Character string
• COM gestisce le stringhe secondo la codifica Unicode
• In Windows le stringhe Unicode corrispondono ad array di WCHAR
• Per ottenere una stringa di caratteri ASCII (TCHAR in Windows),
  bisogna usare un’API di conversione: WideCharToMultiByte
               WideCharToMultiByte
•   int WideCharToMultiByte(
         UINT CodePage, //CP_ACP per ASCII
         DWORD dwFlags, //trattamento dei caratteri composti
         LPCWSTR lpWideCharStr, //la stringa Unicode da convertire
         int cchWideChar, //lungh. stringa Unicode, -1 se null terminated
         LPSTR lpMultiByteStr, //buffer di caratteri per il risultato
         int cbMultiByte, //lungh del buffer di caratteri in byte
         LPCSTR lpDefaultChar, //carattere di default
         LPBOOL lpUsedDefaultChar); //indica uso del caratt. di default

•   Il trattamento dei caratteri composti (parametro dwFlags) è indicato dai
    seguenti possibili flag:
     –   WC_COMPOSITECHECK: controllo sulla presenza di caratt. Composti
     –   WC_SEPCHARS: separa i caratteri composto in 2 caratteri
     –   WC_DISCARDNS: scarta la seconda parte dei caratteri composti
     –   WC_DEFAULTCHAR: usa il carattere di default (parametro lpDefaultChar)
           L’interfaccia IUnknown
• Deve essere supportata da tutti i componenti
• Tutte le interfacce derivano da IUnknown

interface IUnknown {
    virtual HRESULT QueryInterface(IID& iid, void** ppvObj) = 0;
    virtual ULONG AddRef() = 0;
    virtual ULONG Release() = 0;
}

• Implementa le funzionalità essenziali di un componente
    – AddRef e Release per il conteggio dei riferimenti
    – QueryInterface per permettere agli utilizzatori di scoprire a runtime se
      una data interfaccia è supportata da un componente, e in caso positivo
      di ottenerne un riferimento
            Reference Counting
• Serve ad assicurare che i componenti (non le interfacce)
  rimangano vivi finché ci sono utilizzatori che hanno
  accesso ad una o più interfacce
• I metodi AddRef e Release di IUnknown gestiscono il
  conteggio dei riferimenti
   – AddRef aggiunge un nuovo riferimento, viene invocata dalle
     funzioni che restituiscono riferimenti ad interfacce
   – Release deve essere invocata su un riferimento ad un’interfaccia
     quando quel riferimento non è più utilizzato
   – Se si fa una copia di un riferimento ad interfaccia bisogna
     invocare AddRef sul riferimento
• Prestare molta attenzione all’uso di AddRef e Release
  perché il meccanismo del conteggio dei riferimenti è
  fonte di molti errori con COM
                   QueryInterface
HRESULT QueryInterface(IID& iid, void** ppvObj)

• iid
   – Interfaccia per la quale si richiede un riferimento
• ppvObj
   – Riferimento all’interfaccia restituito come risultato di
     QueryInterface


• Se il componente non supporta l’interfaccia richiesta
  viene restituito un valore di ritorno (HRESULT) che
  segnala l’errore
            Esempio
   Componente ShellLink (estratto)
• ShellLink
   – Componente per la creazione di link simbolici (shortcut)
   – CLSID = 0021401-0000-0000-C000-000000000046
• Interfacce supportate
   – {000214ee-0000-0000-c000-000000000046} IShellLink
       • SetPath
       • …
   – {0000010b-0000-0000-c000-000000000046} IPersistFile
       • Save
   – …
                         Esempio
                      Uso di ShellLink
HRESULT hr;
IShellLink* pISL;
IPersistFile* pIPF;

hr = CoCreateInstance(CLSID_ShellLink,
                         NULL,
                         CLSCTX_INPROC_SERVER,
                         IID_IShellLink,
                         (void**)&pISL);
hr = pISL->SetPath(wszPath);

hr = pISL->QueryInterface(IID_IPersistFile, (void**)&pIPF);

hr = pIPF->Save(L"C:\\wallpaper.lnk",FALSE);
pIPF->Release();
pISL->Release();
     Componenti COM (server)
• Un Componente COM implementa ed esporta un
  insieme di Interfacce (oltre a IUnknown)
• L’implementazione delle interfacce è fornita da un
  insieme di CoClass
• Ogni CoClass è univocamente identificata da un CLSID
• Le CoClass di un componente sono contenute nel file
  eseguibile del componente (per esempio Dll o Exe)
• In Windows i CLSID delle CoClass dei componenti
  disponibili sono registrate nel Registry di sistema

								
To top