Microsoft DirectX 9.0 |
The factory template contains the following public member variables:
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)
The two function pointers, m_lpfnNew and m_lpfnInit, use the following type definitions:
typedef CUnknown *(CALLBACK *LPFNNewCOMObject)(LPUNKNOWN pUnkOuter, HRESULT *phr);
typedef void (CALLBACK *LPFNInitRoutine)(BOOL bLoading, const CLSID *rclsid);
The first is the instantiation function for the component. The second is an optional initialization function. If you provide an initialization function, it is called from inside the DLL entry-point function. (The DLL entry-point function is discussed later in this article.)
Suppose you are creating a DLL that contains a component named CMyComponent, which inherits from CUnknown. You must provide the following items in your DLL:
The following example shows how to declare these items:
// 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]);
The CreateInstance method calls the class constructor and returns a pointer to the new class instance. The parameter pUnk is a pointer to the aggregating IUnknown. You can simply pass this parameter to the class constructor. The parameter pHr is a pointer to an HRESULT value. The class constructor sets this to an appropriate value, but if the constructor fails, set the value to E_OUTOFMEMORY.
The NAME macro generates a string in debug builds but resolves to NULL in retail builds. It is used in this example to give the component a name that appears in debug logs but does not occupy memory in the final version.
The CreateInstance method can have any name, because the class factory refers to the function pointer in the factory template. However, g_Templates and g_cTemplates are global variables that the class factory expects to find, so they must have exactly those names.