Menggunakan CUnknown

[Fitur yang terkait dengan halaman ini, DirectShow, adalah fitur warisan. Ini telah digantikan oleh MediaPlayer, IMFMediaEngine, dan Tangkapan Audio/Video di Media Foundation. Fitur-fitur tersebut telah dioptimalkan untuk Windows 10 dan Windows 11. Microsoft sangat menyarankan agar kode baru menggunakan MediaPlayer, IMFMediaEngine dan Audio/Video Capture di Media Foundation alih-alih DirectShow, jika memungkinkan. Microsoft menyarankan agar kode yang ada yang menggunakan API warisan ditulis ulang untuk menggunakan API baru jika memungkinkan.]

DirectShow mengimplementasikan IUnknown di kelas dasar yang disebut CUnknown. Anda dapat menggunakan CUnknown untuk memperoleh kelas lain, hanya mengambil alih metode yang berubah di seluruh komponen. Sebagian besar kelas dasar lainnya di DirectShow berasal dari CUnknown, sehingga komponen Anda dapat mewarisi langsung dari CUnknown atau dari kelas dasar lain.

INonDelegatingUnknown

CUnknown mengimplementasikan INonDelegatingUnknown. Ini mengelola jumlah referensi secara internal, dan dalam sebagian besar situasi kelas turunan Anda dapat mewarisi dua metode penghitungan referensi tanpa perubahan. Ketahuilah bahwa CUnknown menghapus dirinya sendiri ketika jumlah referensi turun ke nol. Di sisi lain, Anda harus mengambil alih CUnknown::NonDelegatingQueryInterface, karena metode di kelas dasar mengembalikan E_NOINTERFACE jika menerima IID selain IID_IUnknown. Di kelas turunan Anda, uji IID antarmuka yang Anda dukung, seperti yang ditunjukkan dalam contoh berikut:

STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv)
{
    if (riid == IID_ISomeInterface)
    {
        return GetInterface((ISomeInterface*)this, ppv);
    }
    // Default: Call parent class method. 
    // The CUnknown class must be in the inheritance chain.
    return CParentClass::NonDelegatingQueryInterface(riid, ppv);
}

Fungsi utilitas GetInterface (lihat Fungsi Pembantu COM) mengatur penunjuk, menaikkan jumlah referensi dengan cara yang aman untuk utas, dan mengembalikan S_OK. Dalam kasus default, panggil metode kelas dasar dan kembalikan hasilnya. Jika Anda berasal dari kelas dasar lain, panggil metode NonDelegatingQueryInterface sebagai gantinya. Ini memungkinkan Anda mendukung semua antarmuka yang didukung oleh kelas induk.

IUnknown

Seperti disebutkan sebelumnya, versi delegasi IUnknown sama untuk setiap komponen, karena tidak lebih dari memanggil instans yang benar dari versi yang tidak mendelegasikan. Untuk kenyamanan, file header Combase.h berisi makro, DECLARE_IUNKNOWN, yang mendeklarasikan tiga metode delegasi sebagai metode sebaris. Ini meluas ke kode berikut:

STDMETHODIMP QueryInterface(REFIID riid, void **ppv) {      
    return GetOwner()->QueryInterface(riid,ppv);            
};                                                          
STDMETHODIMP_(ULONG) AddRef() {                             
    return GetOwner()->AddRef();                            
};                                                          
STDMETHODIMP_(ULONG) Release() {                            
    return GetOwner()->Release();                           
};

Fungsi utilitas CUnknown::GetOwner mengambil pointer ke antarmuka IUnknown komponen yang memiliki komponen ini. Untuk komponen agregat, pemiliknya adalah komponen luar. Jika tidak, komponen memiliki sendiri. Sertakan makro DECLARE_IUNKNOWN di bagian publik definisi kelas Anda.

Konstruktor Kelas

Konstruktor kelas Anda harus memanggil metode konstruktor untuk kelas induk, selain apa pun yang dilakukannya yang khusus untuk kelas Anda. Contoh berikut adalah metode konstruktor umum:

CMyComponent(TCHAR *tszName, LPUNKNOWN pUnk, HRESULT *phr) 
    : CUnknown(tszName, pUnk, phr)
{ 
    /* Other initializations */ 
};

Metode ini mengambil parameter berikut, yang diteruskannya langsung ke metode konstruktor CUnknown .

  • tszName menentukan nama untuk komponen.
  • pUnk adalah penunjuk ke IUnknown agregat.
  • pHr adalah penunjuk ke nilai HRESULT, yang menunjukkan keberhasilan atau kegagalan metode.

Ringkasan

Contoh berikut menunjukkan kelas turunan yang mendukung IUnknown dan antarmuka hipotetis bernama ISomeInterface:

class CMyComponent : public CUnknown, public ISomeInterface
{
public:

    DECLARE_IUNKNOWN;

    STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv)
    {
        if( riid == IID_ISomeInterface )
        {
            return GetInterface((ISomeInterface*)this, ppv);
        }
        return CUnknown::NonDelegatingQueryInterface(riid, ppv);
    }

    CMyComponent(TCHAR *tszName, LPUNKNOWN pUnk, HRESULT *phr) 
        : CUnknown(tszName, pUnk, phr)
    { 
        /* Other initializations */ 
    };

    // More declarations will be added later.
};

Contoh ini mengilustrasikan poin-poin berikut:

  • Kelas CUnknown mengimplementasikan antarmuka IUnknown . Komponen baru mewarisi dari CUnknown dan dari antarmuka apa pun yang didukung komponen. Komponen dapat berasal sebagai gantinya dari kelas dasar lain yang mewarisi dari CUnknown.
  • Makro DECLARE_IUNKNOWN mendeklarasikan metode IUnknown yang mendelegasikan sebagai metode sebaris.
  • Kelas CUnknown menyediakan implementasi untuk INonDelegatingUnknown.
  • Untuk mendukung antarmuka selain IUnknown, kelas turunan harus mengganti metode NonDelegatingQueryInterface dan menguji IID antarmuka baru.
  • Konstruktor kelas memanggil metode konstruktor untuk CUnknown.

Langkah selanjutnya dalam menulis filter adalah mengaktifkan aplikasi untuk membuat instans baru komponen. Ini membutuhkan pemahaman tentang DLL dan hubungannya dengan pabrik kelas dan metode konstruktor kelas. Untuk informasi selengkapnya, lihat Cara Membuat DLL Filter DirectShow.

Cara Menerapkan IUnknown