OPCSERVER 用 VC++.docx
《OPCSERVER 用 VC++.docx》由会员分享,可在线阅读,更多相关《OPCSERVER 用 VC++.docx(28页珍藏版)》请在冰豆网上搜索。
OPCSERVER用VC++
1.生成应用程序框架
1.生成应用程序框架
这里不再对OPC的概念和开发OPCDAserver的必要掌握的COM技术做介绍,相信关于这方面的书籍和资料在网上都可以找得到。
我们言归正传,看看如何建立一个OPCDAServer的基本框架。
1)生成MDI应用程序框架
我们将基于MDI应用程序开发我们的OPCDAServer,这样可以充分利用MFC的一些类库来更好的管理OPCDAServer,也能简化我们的开发。
如果大家有用过Rockwell的RSLinx,就知道这个软件也是基于MFC的MDI应用程序框架的。
打开VS2005,创建一个新的project,选择VisualC++,MDI应用程序。
把project的名字改为OPCTestServer。
2)添加ATL支持
开发OPCDAServer要用到ATL,使用ATL开发COM应用程序,可以大大简化工作量。
上面我们建立了一个支持MFC的应用程序,为了使用ATL,我们需要加入ATL支持。
选择“Project->AddClass…”,在弹出的添加类的对话框里选择“AddATLSupporttoMFC”,确定。
VC会自动添加一个继承于“CAtlMfcModule”的新类“COPCTestServerModule”。
2.实现COPCServer类框架
COPCServer类继承IOPCServer接口,实现IOPCServer的所有接口。
1)OPCDA头文件
在开发opcserver的过程中,我们要包含的头文件主要有:
◆ opcda.h:
定义IOPCServer,IOPCItemMgt,IOPCAsyncIO等OPCDA接口;
◆ opcda_i.c:
ClasssID定义;
◆ opcError.h:
OPCError类型定义;
◆ opccommon.h:
定义IOPCCommon,IOPCServerList等接口
◆ opccommon_i.c:
ClassID定义
这些头文件都可以直接从OPC网站上面的分发包里面安装获得。
为了方便大家使用,我把这些文件上传这里了。
NOTE:
如果机器上以前没有注册过opcproxy.dll,一定要先注册这个dll,这是实现OPCDA接口定义及代理/存根的dll.至于什么是代理/存根,大家请参阅其他的关于COM和DCOM的书籍。
2)添加COPCServer类定义
Project->AddClass->C++Class
VS提示IOPCServer没有找到,是否继续,按“Yes”继续。
我们将在后面添加“IOPCServer”的定义。
NOTE:
这里,为了方便统一管理生成COPCServer对象,我们没有从ATL中的CComCoClass类派生。
将需要包含的头文件(opcda.h,opcda_i.c)拷到include目录下(solution下面的新建的一个子文件夹),在“OPCServer.h”文件中添加:
#include"opcda.h"
编译一下,确保没有错误。
3)实现IUnknown接口
IOPCServer继承IUnknown接口,所以COPCServer首先要实现IUnkonw接口。
a. 添加引用计数变量
private:
ULONG m_lRefCount;
b. 添加接口定义到OPCServer.h:
//theIUnknownFunctions
STDMETHODIMP QueryInterface(REFIIDiid,LPVOID*ppInterface);
STDMETHODIMP_(ULONG)AddRef(void);
STDMETHODIMP_(ULONG)Release(void);
c.添加接口函数实现:
IUnknownInterfaces
1 ////////////////////////////////////////////////////////////////////////////////////
2 STDMETHODIMP_(ULONG) COPCServer:
:
AddRef( void)
3 {
4 return ++m_lRefCount;
5 }
6
7 ////////////////////////////////////////////////////////////////////////////////////
8 STDMETHODIMP_(ULONG) COPCServer:
:
Release( void)
9 {
10 ULONG currentCount = --m_lRefCount;
11
12 // If no references left for this server
13 if ( currentCount == 0)
14 {
15 // Then delete this server.
16 delete this;
17 }
18 return currentCount;
19 }
20
21 ////////////////////////////////////////////////////////////////////////////////////
22 STDMETHODIMP COPCServer:
:
QueryInterface( REFIID iid, LPVOID* ppInterface)
23 {
24 // check valid pointer
25 if ( ppInterface == NULL)
26 return E_INVALIDARG;
27
28 // default return is NULL in case of error
29 *ppInterface = NULL;
30
31 if ( iid == IID_IUnknown )
32 {
33 *ppInterface = (IUnknown*) this;
34 }
35
36 else if ( iid == IID_IOPCServer)
37 {
38 *ppInterface = (IOPCServer*) this;
39 }
40
41 if ( *ppInterface == NULL)
42 return E_NOINTERFACE;
43
44 AddRef();
45 return S_OK;
46 }
47
4.添加IOPCServer接口函数
a.在"opcserver.h"中添加函数定义
IOPCServerFunctions
1 // the IOPCServer Functions
2 STDMETHODIMP GetStatus(
3 OPCSERVERSTATUS** ppServerStatus);
4 STDMETHODIMP GetErrorString(
5 HRESULT hr,
6 LCID locale,
7 LPWSTR *ppstring);
8 STDMETHODIMP AddGroup(
9 LPCWSTR szName,
10 BOOL bActive,
11 DWORD dwRequestedUpdateRate,
12 OPCHANDLE hClientGroup,
13 LONG *pTimeBias,
14 FLOAT *pPercentDeadband,
15 DWORD dwLCID,
16 OPCHANDLE *phServerGroup,
17 DWORD *pRevisedUpdateRate,
18 REFIID riid,
19 LPUNKNOWN *ppUnk
20 );
21 STDMETHODIMP GetGroupByName(
22 LPCWSTR szGroupName,
23 REFIID riid, LPUNKNOWN *ppUnk);
24 STDMETHODIMP RemoveGroup(
25 OPCHANDLE groupHandleID,
26 BOOL bForce);
27
28 STDMETHODIMP CreateGroupEnumerator(
29 OPCENUMSCOPE dwScope,
30 REFIID riid,
31 LPUNKNOWN *ppUnk
32 );
b.在"OPCServer.cpp"中添加函数实现
Code
//////////////////////////////////////////////////////////////////////////////////
// the IOPCServer Functions
STDMETHODIMP COPCServer:
:
GetStatus( OPCSERVERSTATUS** ppServerStatus)
{
return S_OK;
}
//////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP COPCServer:
:
GetErrorString( HRESULT hr, LCID locale,
LPWSTR *ppstring)
{
return S_OK;
}
//////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP COPCServer:
:
AddGroup(
LPCWSTR szName,
BOOL bActive,
DWORD dwRequestedUpdateRate,
OPCHANDLE hClientGroup,
LONG *pTimeBias,
FLOAT *pPercentDeadband,
DWORD dwLCID,
OPCHANDLE *phServerGroup,
DWORD *pRevisedUpdateRate,
REFIID riid,
LPUNKNOWN *ppUnk
)
{
return S_OK;
}
//////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP COPCServer:
:
GetGroupByName(
LPCWSTR szGroupName,
REFIID riid, LPUNKNOWN *ppUnk)
{
return S_OK;
}
//////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP COPCServer:
:
RemoveGroup( OPCHANDLE groupHandleID,
BOOL bForce)
{
return S_OK;
}
//////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP COPCServer:
:
CreateGroupEnumerator(
OPCENUMSCOPE dwScope,
REFIID riid,
LPUNKNOWN *ppUnk
)
{
return S_OK;
}
这些接口函数现在都是空函数,我们会在以后的章节中逐步实现这些函数。
3.实现OPC类工厂
这节我们将介绍com类工厂的实现。
1)准备工作:
在OPCServer运行过程中,对应每一个OPCclient,都会生成一个COPCServer对象,为了管理所有的OPCserver对象,我们先创建一个OPCserver的管理类CServerMgr.
"Project->AddClass..->C++class"
CServerMgr头文件如下:
Code
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 m_serverList;
18 };
AddServerToList()实现:
CServerMgr:
:
AddServerToList
1 void CServerMgr:
:
AddServerToList(COPCServer* pServer)
2 {
3 if (pServer)
4 m_serverList.AddTail(pServer);
5 }
RomoveServerFromList()实现:
Code
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。
类工厂定义如下:
COPCClassFactory
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()
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()
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()
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"
externCServerMgrg_ServerMgr;
CreateInstance
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);
2