如何实现Filter 的类厂对象
所有的com 组件为了实现二进制的封装,所以连创建的接口都封装了,因此每个com 对象
都有个类对象(也叫类厂对象,本身也是com 对象,用来创建com 组件)来创建com 组件。
下面温习一下com 组件的创建过程,其中涉及到几个函数
所有的com 组件为了实现二进制的封装,所以连创建的接口都封装了,因此每个com 对象
都有个类对象(也叫类厂对象,本身也是com 对象,用来创建com 组件)来创建com 组件。
下面温习一下com 组件的创建过程,其中涉及到几个函数
1 当客户端要创建一个com 组件时,它通过底层的COM API 函数 CoGetClassObject()使用SCM 的服务,这个函数请SCM 把一个指针
绑定到客户端请求的com 组件的类对象上,其实在CoGetClassObjec(t )里它装载了该DLL 的库,通过该dll 的导出函数
DllGetClassObject();DllGetClassObject 根据客户端提供的com 组件CLASSID,返回该com 组件类对象的指针。
下面com 组件的创建就是SCM 无关了。
2 客户端利用组件的类对象(类厂对象)的IClassFactory::CreateInstance 方法创建com 组件。
Filter 在这里使用了一个类厂模板类来当作Filter 的类厂对象。
下面看看类厂在DShow 是怎么工作的。
类厂对象也是一个com组件。本来DllGetClassObject 是我们自己写的一个函数,在directshow
里已经完成了,我们不用自己来完成它了。它的功能就是来寻找这个DLL 中的类厂对象,看
是否有符合客户端请求的类厂对象。
DLL 里声明了一个全局的类厂模板数组,当DllGetClassObject 请求类厂对象的时候,它就
搜索这个数组,看是否有和CLSID 匹配的类厂对象。当它找到一个匹配的CLSID,它就创建
一个类厂对象,然后讲类厂指针返回给CoGetClassObject,然后客户端可以根据返回去的类厂
指针,调用 IClassFactory::CreateInstance 方法创建组件,类厂就根据数组里定义的方法创
建com 组件。
factory template 包含下列变量:
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 (forfilters)
其中的两个函数指针m_lpfnNew and m_lpfnInit 使用下面的定义
typedef CUnknown *(CALLBACK *LPFNNewCOMObject)(LPUNKNOWN pUnkOuter, HRESULT *phr);
typedef void (CALLBACK *LPFNInitRoutine)(BOOL bLoading, const CLSID *rclsid);
typedef CUnknown *(CALLBACK *LPFNNewCOMObject)(LPUNKNOWN pUnkOuter, HRESULT *phr);
typedef void (CALLBACK *LPFNInitRoutine)(BOOL bLoading, const CLSID *rclsid);
你可以参照如下的方式定义你的类厂对象
假如下面是你的com 组件创建函数,
CUnknown * WINAPI CMyFilter::CreateInstance(LPUNKNOWN pUnk, HRESULT *pHr)
{
CMyFilter *pFilter = new CMyFilter(NAME("my Filter"), pUnk, pHr);
if (pFilter== NULL)
{
*pHr = E_OUTOFMEMORY;
}
return pFilter;
}
假如下面是你的com 组件创建函数,
CUnknown * WINAPI CMyFilter::CreateInstance(LPUNKNOWN pUnk, HRESULT *pHr)
{
CMyFilter *pFilter = new CMyFilter(NAME("my Filter"), pUnk, pHr);
if (pFilter== NULL)
{
*pHr = E_OUTOFMEMORY;
}
return pFilter;
}
你可以声明自己的类厂数组如下:
如果在这个com 组件中你要支持多个filter,你可以在这个数组中继续添加就是了。
CFactoryTemplate g_Templates[1] =
{
{
L"my filter", // Name
&CLSID_MYFilter, // CLSID
CMyFilter::CreateInstance, // Method to create an instance of MyComponent
NULL, // Initialization function
&sudInfTee // Set-up information (for filters)
}
};
CFactoryTemplate g_Templates[1] =
{
{
L"my filter", // Name
&CLSID_MYFilter, // CLSID
CMyFilter::CreateInstance, // Method to create an instance of MyComponent
NULL, // Initialization function
&sudInfTee // Set-up information (for filters)
}
};
int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);