Поделиться через


Массив шаблонов фабрики

[Функция, связанная с этой страницей, DirectShow, является устаревшей функцией. Он был заменен MediaPlayer, IMFMediaEngineи аудио и видеозахват в Media Foundation. Эти функции оптимизированы для Windows 10 и Windows 11. Корпорация Майкрософт настоятельно рекомендует использовать новый код MediaPlayer, IMFMediaEngine и аудио-видеозахват в Media Foundation вместо DirectShowпо возможности. Корпорация Майкрософт предлагает, что существующий код, использующий устаревшие API, будет перезаписан для использования новых API, если это возможно.]

Шаблон фабрики содержит следующие открытые переменные-члены:

const WCHAR *              m_Name;                // Name
const CLSID *              m_ClsID;               // CLSID
LPFNNewCOMObject           m_lpfnNew;             // Function to create an instance
                                                  //   of the component
LPFNInitRoutine            m_lpfnInit;            // Initialization function (optional)
const AMOVIESETUP_FILTER * m_pAMovieSetup_Filter; // Set-up information (for filters)

Два указателя функции, m_lpfnNew и m_lpfnInit, используют следующие определения типов:

typedef CUnknown *(CALLBACK *LPFNNewCOMObject)(LPUNKNOWN pUnkOuter, HRESULT *phr);
typedef void (CALLBACK *LPFNInitRoutine)(BOOL bLoading, const CLSID *rclsid);

Первое — это функция создания экземпляра компонента. Второй — это необязательная функция инициализации. Если вы предоставляете функцию инициализации, она вызывается из-за функции точки входа DLL. (Функция точки входа DLL рассматривается далее в этой статье.)

Предположим, вы создаете библиотеку DLL, содержащую компонент CMyComponent, который наследует от CUnknown. В библиотеке DLL необходимо указать следующие элементы:

  • Функция инициализации— открытый метод, возвращающий новый экземпляр CMyComponent.
  • Глобальный массив шаблонов фабрики с именем g_Templates. этот массив содержит шаблон фабрики для CMyComponent.
  • Глобальная переменная с именем g_cTemplates, указывающая размер массива.

В следующем примере показано, как объявить эти элементы:

// Public method that returns a new instance. 
CUnknown * WINAPI CMyComponent::CreateInstance(LPUNKNOWN pUnk, HRESULT *pHr) 
{
    CMyComponent *pNewObject = new CMyComponent(NAME("My Component"), pUnk, pHr );
    if (pNewObject == NULL) {
        *pHr = E_OUTOFMEMORY;
    }
    return pNewObject;
} 

CFactoryTemplate g_Templates[1] = 
{
    { 
      L"My Component",                // Name
      &CLSID_MyComponent,             // CLSID
      CMyComponent::CreateInstance,   // Method to create an instance of MyComponent
      NULL,                           // Initialization function
      NULL                            // Set-up information (for filters)
    }
};
int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);    

Метод CreateInstance вызывает конструктор классов и возвращает указатель на новый экземпляр класса. Параметр pUnk — это указатель на агрегирование IUnknown. Этот параметр можно просто передать конструктору классов. Параметр pHr — это указатель на значение HRESULT. Конструктор класса задает для этого соответствующее значение, но если конструктор завершается ошибкой, задайте значение E_OUTOFMEMORY.

Макрос NAME создает строку в отладочных сборках, но разрешает null в розничных сборках. Он используется в этом примере, чтобы дать компоненту имя, которое отображается в журналах отладки, но не занимает память в окончательной версии.

Метод CreateInstance может иметь любое имя, так как фабрика классов ссылается на указатель функции в шаблоне фабрики. Однако g_Templates и g_cTemplates являются глобальными переменными, которые фабрика классов ожидает найти, поэтому они должны иметь именно эти имена.

Создание библиотеки DLL фильтра DirectShow