现在就需要所有客户端指向同一进程内组件实例,如何做到?
解决方案 »
- vs2010 c++ ADO 连接 oracle 11G 的问题
- MFC中使用了Excel的操作,讨论字符的读入问题
- 怎样检测系统有没有视频捕获设备?
- 新手提问:希望能生成emf文件,但内容为空,和别的对照,实在看不出哪有问题,谢谢
- 一个关于工具栏提示的问题!
- c和c++ 的兼容问题,高分请高手帮忙!(在线等待……)
- 怎样实现CRichEditCtrl控件右边滚动条的自动下滚???
- 请教关于CMscomm的方法如: *.GetOutPut()
- 一个vc的错误问题分析(100分
- 把一个控件工程移到另一个控件工程时遇到的问题--100分
- 请教:生成dll遇到了麻烦,老是说文件损坏,请教
- 导入d3d9.lib出错
如果是进程内组件,如何实现“单实例”?
这个问题一直困扰我!
class CMyObject : public......
{
DECLARE_CLASSFACTORY_SINGLETON(CMyObject)
};
而对进程内组件,每次创建组件时类厂需要重新创建。
试过,都不行!
能否给个提示?如何作?
<1> 一个进程(1个可执行的主程序);
<2> 里面创建多个普通的进程内组件(用ATL创建的进程内DLL,里面创建ATL简单对象);
<3> 然后该主程序对同一个CLSID创建多个对象实例。是这样吗?我没理解错吧?然后加上DECLARE_CLASSFACTORY_SINGLETON,却发现多个实例不是相同的实例??你是怎么测试的?有两个显然的方法可以确认是否是单实例:
<1> 同一个CLSID创建两个对象,索取相同接口,获得两个接口指针,这两个指针的地址值应当相等;
<2> 在接口上定义GetValue(int),SetValue(int)两个方法供测试,SetValue将得到的数存储在成员变量里,那么两个对象的GetValue应当获得相同的值(这简直是废话,不要取笑)。你怎么可能无法创建单实例对象呢?还是你说的“同一进程内组件实例”不是我理解的“单实例”??
<1> 一个进程p1(1个可执行的主程序);
<2> 里面创建1个普通的进程内组件A(用ATL创建的进程内DLL,里面创建ATL简单对象);
<3> 然后该主程序对同这个CLSID创建1个对象实例--a1<4> 起另外一个进程p2(1个可执行的主程序);
<5> 当其发现组件A已有一个对象实例a1时,就不再创建新的实例。就使用现有的实例a1.也就是进程p1,p2共享同一组件实例a1。不知我说清楚了没有?
OBJECT_ENTRY_AUTO(__uuidof(obj), Cobj)展开后是这样:
__declspec(selectany) ATL::_ATL_OBJMAP_ENTRY __objMap_Cobj =
{
&__uuidof(obj),
Cobj::UpdateRegistry,
Cobj::_ClassFactoryCreatorClass::CreateInstance,
Cobj::_CreatorClass::CreateInstance,
NULL,
0,
Cobj::GetObjectDescription,
Cobj::GetCategoryMap,
Cobj::ObjectMain
};extern "C" __declspec(allocate("ATL$__m")) __declspec(selectany)
ATL::_ATL_OBJMAP_ENTRY* const __pobjMap_Cobj = &__objMap_Cobj;__pragma(comment(linker, "/include:___pobjMap_Cobj"));
说实话,里面的大部分编译选项我都看不太明白,但是或许可以大致这样解释:
<1> ATL向导为组件Cobj定义了一个全局结构体变量__objMap_Cobj,该结构体存储了组件Cobj的很多信息,尤其是用于创建对象的静态函数CreateInstance;
<2> ATL向导将__objMap_Cobj赋值给了一个外部的全局对象__pobjMap_Cobj,由于不懂__declspec(allocate("ATL$__m"))啥意思,所以不能确定这个extern的对象在哪里;然后,我们再看看供Client获得类厂的方法“DllGetClassObject”。其中具体为Client获取类厂的调用是向导生成的这句:
_AtlModule.DllGetClassObject(rclsid, riid, ppv);展开后看到如下代码:
ATLINLINE ATLAPI AtlComModuleGetClassObject(_ATL_COM_MODULE* pComModule, REFCLSID rclsid, REFIID riid, LPVOID* ppv)
{
ATLASSERT(pComModule != NULL);
if (pComModule == NULL)
return E_INVALIDARG;
if (pComModule->cbSize == 0) // Module hasn't been initialized
return E_UNEXPECTED; if (ppv == NULL)
return E_POINTER;
*ppv = NULL; HRESULT hr = S_OK; for (_ATL_OBJMAP_ENTRY** ppEntry = pComModule->m_ppAutoObjMapFirst; ppEntry < pComModule->m_ppAutoObjMapLast; ppEntry++)
{
if (*ppEntry != NULL)
{
_ATL_OBJMAP_ENTRY* pEntry = *ppEntry;
if ((pEntry->pfnGetClassObject != NULL) && InlineIsEqualGUID(rclsid, *pEntry->pclsid))
{
if (pEntry->pCF == NULL)
{
CComCritSecLock<CComCriticalSection> lock(pComModule->m_csObjMap, false);
hr = lock.Lock();
if (FAILED(hr))
{
ATLTRACE(atlTraceCOM, 0, _T("ERROR : Unable to lock critical section in AtlComModuleGetClassObject\n"));
ATLASSERT(0);
break;
}
if (pEntry->pCF == NULL)
hr = pEntry->pfnGetClassObject(pEntry->pfnCreateInstance, __uuidof(IUnknown), (LPVOID*)&pEntry->pCF);
}
if (pEntry->pCF != NULL)
hr = pEntry->pCF->QueryInterface(riid, ppv);
break;
}
}
} if (*ppv == NULL && hr == S_OK)
hr = CLASS_E_CLASSNOTAVAILABLE;
return hr;
}关键就在这个变量pComModule->m_ppAutoObjMapFirst里,感觉它肯定与先前的全局变量__objMap_Cobj有关联……………………所以你说进程内类厂会“重建”我不知道怎么重建法?