Suschnost' tehnologii SOM
Authors: Boks D.
Published year:
Pages: 30-31/103
Buy this book on amazon.com >>

C++ IUnknown , ÷ C++ (runtime layer) . IUnknown , . C++, C++ , , ÷ , ÷ .

Visual Basic Java, ÷ C++, QueryInterface , AddRef Release . IUnknown ø. Java QueryInterface :

public void TryToSnoreAndIgnore(Object obj) { 
    IPug pug; 
    try { 
       pug = (IPug)obj; 
       // VM calls QueryInterface 
       // VM вызывает QueryInterface 
       pug.Snore(); 
    } catch (Throwable ex) { 
       // ignore method or QI failures 
       // игнорируем сбой метода или QI 
} 

ICat cat; 

try { 
    cat = (ICat)obj; 
    // VM calls QueryInterface 
    // VM вызывает QueryInterface 
    cat.IgnoreMaster(); 
} catch (Throwable ex) { 
    // ignore method or QI failures 
    // игнорируется сбой метода или QI 
    } 
}

Visual Basic . , , ø (VM) Visual Basic ÷ QueryInterface :

Sub TryToSnoreAndIgnore(obj as Object) 
On Error Resume Next 
' ignore errors 
' игнорируем ошибки 
Dim pug as IPug 
Set pug = obj 
' VM calls QueryInterface 
' VM вызывает QueryInterface 
If Not (pug is Nothing) Then 
  pug.Snore 
End if 
Dim cat as ICat 
Set cat = obj 
' VM calls QueryInterface 
' VM вызывает QueryInterface 
If Not (cat is Nothing) Then 
  cat.IgnoreMaster 
End if End Sub

ø, Java, Visual Basic, QueryInterface ÷. ø ÷ ÷ AddRef Release , .

, C++, , ÷ . ( raw ) IUnknown . :

  1. Add/Release .
  2. ÷ ÷ , ÷ ÷ ø () ÷.
  3. C++ QueryInterface .
  4. ÷ ( ) .

÷ ÷ . -, ÷ ÷ , ø, . Visual C++ 5.0, , ÷ ( MSC, ATL, Direct-to-COM), ÷ , . 1995 1996 " C++ Report " , ÷ 1 . , , -, . ÷ ø, ÷ , . , SmartInterface , ø (template) : C++ IID . IUnknown :

#include "smartif.h" 
void TryToSnoreAndIgnore(/* [in] */ IUnknown *pUnk) 
{ 
      // copy constructor calls QueryInterface 
      // конструктор копирования вызывает QueryInterface 
    SmartInterface<IPug, &IID_IPug> pPug = pUnk; 
    if (pPug) 
      // typecast operator returns null-ness 
      // оператор приведения типа возвращает нуль 
        pPug->Snore(); 
      // operator-> returns safe raw ptr 
      // оператор -> возвращает прямой указатель 
      // copy constructor calls QueryInterface 
      // конструктор копирования вызывает QueryInterface 
    SmartInterface<ICat, &IID_ICat> pCat = pUnk; 
    if (pCat) 
      // typecast operator returns null-ness 
      // оператор приведения типа возвращает нуль 
        pCat->IgnoreMaster(); 
      // operator-> returns safe raw ptr 
      // оператор -> возвращает прямой указатель 
      // destructors release held pointers on leaving scope 
      // деструкторы освобождают удерживаемые указатели при 
      // выходе из области действия 
}

÷ , ÷ , ; ÷ ø , , . ø , ÷; , . , ÷ -> . , Release - , ÷ ÷ Release ø .


1 http:/www.develop.com/dbox/cxx/InterfacePtr.htm http://www.develop.com/dbox/cxx/SmartPtr.htm.

QueryInterface

÷ QueryInterface , , ÷ , C++. , , . ÷ ø ø ø . , ÷ , IID - , - . , QueryInterface , , , ø if , ÷ static_cast ( static_cast , ÷ vptr ).

× QueryInterface , ÷ , ÷ . , IID , vptr ø . , ÷ ÷ , . ÷ inttable.h , :

// inttable.h (book-specific header file)
// inttable.h (заголовочный файл, специфический для этой книги) 
// typedef for extensibility function 
// typedef для функции расширяемости 

typedef HRESULT (*INTERFACE_FINDER) 
(void *pThis, DWORD dwData, REFIID riid, void **ppv); 

// pseudo-function to indicate entry is just offset 
// псевдофункция для индикации того, что запись просто 
// является смещением 

#define ENTRY_IS_OFFSET INTERFACE_FINDER(-1) 
// basic table layout 
// представление базовой таблицы 

typedef struct INTERFACE_ENTRY { 
    const IID * pIID; 
      // the IID to match 
      // соответствующий IID 
    INTERFACE_FINDER pfnFinder; 
      // функция finder 
    DWORD dwData; 
      // offset/aux data
      // данные по offset/aux 
} INTERFACE_ENTRY;

÷ :

// Inttable.h (book-specific header file)
// Inttable.h (заголовочный файл, специфический для данной книги) 

#define BASE_OFFSET(ClassName, BaseName) \ 
(DWORD(static_cast<BaseName*>(reinterpret_cast\ 
<ClassName*>(0x10000000))) - 0х10000000) 

#define BEGIN_INTERFACE_TABLE(ClassName) \ 
typedef ClassName _ITCls;\ 
const INTERFACE_ENTRY *GetInterfaceTable(void) {\ 
static const INTERFACE_ENTRY table [] = {\ 

#define IMPLEMENTS_INTERFACE(Itf) \ 
{&IID_##Itf,ENTRY_IS_OFFSET,BASE_OFFSET(_ITCls,Itf)}, 

#define IMPLEMENTS_INTERFACE_AS(req, Itf) \ 
{&IID_##req,ENTRY_IS_OFFSET, BASE_OFFSET(_ITCls, Itf)}, 

#define END_INTERFACE_TABLE() \ 
{ 0, 0, 0 } }; return table; }

, ÷ , - , QueryInterface . Inttable.h :

// inttable.cpp (book-specific source file)
// inttable.h (заголовочный файл, специфический для данной книги) 
HRESULT InterfaceTableQueryInterface(void *pThis, 
                                     const INTERFACE_ENTRY *pTable, 
                                     REFIID riid, void **ppv) 
{ 
    if (InlineIsEqualGUID(riid, IID_IUnknown)) { 
        // first entry must be an offset 
        // первый элемент должен быть смещением 
        *ppv = (char*)pThis + pTable->dwData; 
        ((Unknown*) (*ppv))->AddRef () ; // A2 
        return S_OK; 
    } 
    else { 
        HRESULT hr = E_NOINTERFACE; 
        while (pTable->pfnFinder) { // null fn ptr == EOT 
            if (!pTable->pIID  InlineIsEqualGUID(riid,*pTable->pIID)) { 
                if (pTable->pfnFinder == ENTRY_IS_OFFSET) { 
                    *ppv = (char*)pThis + pTable->dwData; 
                    ((IUnknown*)(*ppv))->AddRef(); // A2 
                    hr = S_OK; 
                    break; 
                } 
                else { 
                    hr = pTable->pfnFinder(pThis, pTable->dwData, riid, ppv); 
                    if (hr == S_OK) break; 
                } 
             } 
             pTable++; 
        } 
        if (hr != S_OK) *ppv = 0; 
        return hr; 
    } 
}

÷ ø , InterfaceTableQueryInterface , ø IID , , . ø ø IsEqualGUID , ø , 20-30 ø , . InterfaceTableQueryInterface , .

÷ C++, ÷ , -. ÷ impunk.h QueryInterface , AddRef Release , ÷ :

// impunk.h (book-specific header file)
// impunk.h (заголовочный файл, специфический для данной книги) 
// AUTO_LONG is just a long that constructs to zero 
// AUTO_LONG - это просто long, с конструктором, 
// устанавливающим значение в О 

struct AUTO_LONG { 
    LONG value; 
    AUTO_LONG (void) : value (0)  
}; 

#define IMPLEMENT_UNKNOWN(ClassName) \ 
AUTO_LONG m_cRef;\ 
STDMETHODIMP QueryInterface(REFIID riid, void **ppv){\ 
return InterfaceTableQueryInterface(this,\ 
GetInterfaceTable(), riid, ppv);\ 
}\ 
STDMETHODIMP_(ULONG) AddRef(void) { \ 
return InterlockedIncrement(&m_cRef.value); \ 
}\ 
STDMETHODIMP_(ULONG) Release(void) {\ 
ULONG res = InterlockedDecrement(&m_cRef.value) ;\ 
if (res == 0) \ 
delete this;\ 
return res;\ 
}\

÷ , ÷ .

PugCat , ÷ ø , ø QueryInterface , AddRef Release :

class PugCat : public IPug, public ICat {
  protected: 
    virtual ~PugCat(void); 
  public: 
    PugCat(void); 
      // IUnknown methods 
      // методы IUnknown 
    IMPLEMENT_UNKNOWN (PugCat) 
    BEGIN_INTERFACE_TABLE(PugCat) 
      IMPLEMENTS_INTERFACE(IPug) 
      IMPLEMENTS_INTERFACE(IDog) 
      IMPLEMENTS_INTERFACE_AS(IAnimal,IDog) 
      IMPLEMENTS_INTERFACE(ICat)
    END_INTERFACE_TABLE() 
      // IAnimal methods 
      // методы IAnimal 
    STDMETHODIMP Eat(void); 
      // IDog methods 
      // методы IDog 
    STDMETHODIMP Bark(void); 
      // IPug methods 
      // методы IPug 
    STDMETHODIMP Snore(void); 
      // ICat methods 
      // методы ICat 
    STDMETHODIMP IgnoreMaster(void); 
};

, IUnknown . , ÷ , , .

Suschnost' tehnologii SOM
Authors: Boks D.
Published year:
Pages: 30-31/103
Buy this book on amazon.com >>

Similar books on Amazon