这节我们将介绍com类工厂的实现。
1) 准备工作:
在OPC Server运行过程中,对应每一个OPC client,都会生成一个COPCServer对象,为了管理所有的OPC server对象,我们先创建一个OPC server的管理类CServerMgr.
"Project->Add Class.. ->C++ class"
CServerMgr头文件如下:
1 #pragma once
2
3 #include "OPCServer.h"
4
5 class CServerMgr
6 {
7 public:
8 CServerMgr(void);
9 ~CServerMgr(void);
10
11 //methods
12 void AddServerToList(COPCServer* pServer);
13 void RemoveServerFromList(COPCServer* pServer);
14
15 //members
16 public:
17 CTypedPtrList<CPtrList, COPCServer *> m_serverList;
18 };
AddServerToList()实现:
1 void CServerMgr::AddServerToList(COPCServer* pServer)
2 {
3 if (pServer)
4 m_serverList.AddTail(pServer);
5 }
RomoveServerFromList() 实现:
1 void CServerMgr::RemoveServerFromList(COPCServer* pServer)
2 {
3 if (pServer)
4 {
5 if (m_serverList.GetCount() > 0)
6 {
7 POSITION pos = m_serverList.Find(pServer);
8 if (pos)
9 m_serverList.RemoveAt(pos);
10 }
11 }
12 }
在ServerMgr.cpp文件中定义CServerMgr全局变量:
CServerMgr g_ServerMgr;
2) 实现OPC 类工厂
这里实现的类工厂继承IClassFactory。
类工厂定义如下:
1 #pragma once
2 #include "ocidl.h"
3
4 class COPCClassFactory :
5 public IClassFactory
6 {
7 public:
8 COPCClassFactory(void);
9 ~COPCClassFactory(void);
10
11 //IUnknown interfaces
12 STDMETHODIMP QueryInterface( REFIID iid, LPVOID* ppInterface);
13 STDMETHODIMP_(ULONG) AddRef( void);
14 STDMETHODIMP_(ULONG) Release( void);
15
16 //IClassFactory interfaces
17 STDMETHODIMP CreateInstance( LPUNKNOWN pUnkOuter, REFIID riid, LPVOID* ppvObject);
18 STDMETHODIMP LockServer( BOOL fLock);
19
20 private:
21 ULONG m_lRefCount;
22 };
现在我们来看看如何具体实现类工厂:
a. 初始化引用计数
m_lRefCount = 0;
b. QueryInterface()
1 // QueryInterface()
2 // Implementation of the standard IUnknown QueryInterface() function for the sample OPC class factory.
3
4 STDMETHODIMP COPCClassFactory::QueryInterface( REFIID iid, LPVOID* ppInterface)
5 {
6 if ( ppInterface == NULL)
7 return E_INVALIDARG;
8
9 if ( iid == IID_IUnknown || iid == IID_IClassFactory)
10 {
11 *ppInterface = this;
12 }
13 else
14 *ppInterface = NULL;
15
16 if( *ppInterface )
17 {
18 AddRef();
19 return S_OK;
20 }
21
22 return E_NOINTERFACE;
23 }
c. AddRef()
1 // AddRef()
2 // Implementaion of the standard IUnknown AddRef() function for the sample OPC class factory.
3
4 STDMETHODIMP_(ULONG) COPCClassFactory::AddRef( void)
5 {
6 return ++m_lRefCount;
7 }
d. Release()
1 // Release()
2 // Implementation of the standard IUnknown Release() function for the sample OPC class factory.
3
4 STDMETHODIMP_(ULONG) COPCClassFactory::Release( void)
5 {
6 ULONG currentCount = --m_lRefCount;
7 if ( currentCount == 0)
8 delete this;
9 return currentCount;
10 }
e. CreateInstance()
在"OPCClassFactory.cpp"定义:
#include "ServerMgr.h"
extern CServerMgr g_ServerMgr;
1 // CreateInstance()
2 // This function creates an instance of the OPC sample server.
3 STDMETHODIMP COPCClassFactory::CreateInstance( LPUNKNOWN pUnkOuter, REFIID riid, LPVOID* ppvObject)
4 {
5 COPCServer* pServer = new COPCServer;
6 if ( pServer == NULL)
7 {
8 TRACE( "OPCClassFactory::CreateInstance() - Not enough memory to create OPC Server object, returning E_OUTOFMEMORY\n" );
9 return E_OUTOFMEMORY;
10 }
11 //get requested interface
12 HRESULT hr = pServer->QueryInterface( riid, ppvObject);
13 if ( FAILED( hr))
14 {
15 delete pServer;
16 }
17 else
18 {
19 g_ServerMgr.AddServerToList(pServer);
20 }
21 return hr;
22 }
23
f. LockServer()
1 // LockServer()
2 // This is a standard implementation of the IClassFactory::LockServer() function that either
3 // adds or removes a lock on the server.
4 // This is very useful if our server is an inproc process.
5 // The count determines whether the dll can be unloaded or not.
6 STDMETHODIMP COPCClassFactory::LockServer( BOOL fLock)
7 {
8 if ( fLock)
9 g_dwLockCount++;
10 else
11 g_dwLockCount--;
12
13 return S_OK;
14 }
3) 注册类厂
因为我们的server是进程外server,所以要调用CoRegisterClassObject注册类厂对象。
a. 在"COPCTestServerApp"类中添加变量:
IClassFactory* m_pFactory;
DWORD m_dwRegisterID;
并在构造函数初始化:
m_pFactory = NULL;
m_dwRegisterID = 0;
b. 定义OPC server GUID
在"OPCTestServer.cpp"中添加:
//Server GUID
// {2BBA92EA-809B-4717-B3F9-750422C937B2}
DEFINE_GUID(CLSID_OPCTestServer, 0x2bba92ea, 0x809b, 0x4717, 0xb3, 0xf9, 0x75, 0x4, 0x22, 0xc9, 0x37, 0xb2);
c. 在InitInstance()中添加:
1 //Register class object
2 if (m_pFactory == NULL)
3 {
4 m_pFactory = new COPCClassFactory();
5 m_pFactory->AddRef();
6
7 if (FAILED( CoRegisterClassObject( CLSID_OPCTestServer,
8 m_pFactory, CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &m_dwRegisterID)))
9 {
10 TRACE("CoRegisterClassObject Failed.");
11 return FALSE;
12 }
13 }
并注释掉前面在添加ATL支持时VC自动加入的code:
//#if !defined(_WIN32_WCE) || defined(_CE_DCOM)
// Register class factories via CoRegisterClassObject().
//if (FAILED(_AtlModule.RegisterClassObjects(CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE)))
// return FALSE;
//#endif // !defined(_WIN32_WCE) || defined(_CE_DCOM)
d. 在Exitinstance()中添加
1 //#if !defined(_WIN32_WCE) || defined(_CE_DCOM)
2 // _AtlModule.RevokeClassObjects();
3 //#endif
4
5 //Revoke class object
6 if (m_pFactory)
7 {
8 ::CoRevokeClassObject(m_dwRegisterID);
9 m_pFactory->Release();
10 }