您好,欢迎来到意榕旅游网。
搜索
您的当前位置:首页OPCSERVER 用 VC++

OPCSERVER 用 VC++

来源:意榕旅游网
1. 生成应用程序框架

1. 生成应用程序框架

这里不再对OPC的概念和开发OPC DA server的必要掌握的COM技术做介绍,相信关于这方面的书籍和资料在网上都可以找得到。我们言归正传,看看如何建立一个OPC DA Server的基本框架。

1)生成MDI应用程序框架

我们将基于MDI应用程序开发我们的OPC DA Server,这样可以充分利用MFC的一些类库来更好的管理OPCDA Server,也能简化我们的开发。如果大家有用过Rockwell 的RSLinx,就知道这个软件也是基于MFC 的 MDI应用程序框架的。

打开VS2005,创建一个新的project,选择Visual C++,MDI应用程序。把project的名字改为OPCTestServer。

2)添加ATL支持

开发OPCDA Server要用到ATL,使用ATL开发COM应用程序,可以大大简化工作量。上面我们建立了一个支持MFC的应用程序,为了使用ATL,我们需要加入ATL支持。 选择“Project->Add Class … ”,在弹出的添加类的对话框里选择“Add ATL Support to MFC”, 确定。VC会自动添加一个继承于“CAtlMfcModule”的新类“COPCTestServerModule”。

2. 实现COPCServer类框架

COPCServer类继承IOPCServer接口,实现IOPCServer的所有接口。 1) OPC DA头文件

在开发opc server的过程中,我们要包含的头文件主要有:

 opcda.h: 定义IOPCServer, IOPCItemMgt, IOPCAsyncIO等OPC DA接

口;

 opcda_i.c : Classs ID 定义;  opcError.h: OPC Error 类型定义;

 opccommon.h: 定义IOPCCommon,IOPCServerList等接口  opccommon_i.c: Class ID 定义

这些头文件都可以直接从OPC 网站上面的分发包里面安装获得。为了方便大家使用,我把这些文件上传这里了。

http://files.cnblogs.com/opc521/OPCDAInclude.zip

NOTE:如果机器上以前没有注册过opcproxy.dll,一定要先注册这个dll,这是实现OPC DA接口定义及代理/存根的dll. 至于什么是代理/存根,大家请参阅其他的关于COM 和DCOM的书籍。

2)添加COPCServer类定义

Project->Add Class -> 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: // the IUnknown Functions

STDMETHODIMP QueryInterface(REFIIDiid, LPVOID* ppInterface); STDMETHODIMP_(ULONG) AddRef( void); STDMETHODIMP_(ULONG) Release( void);

c. 添加接口函数实现:

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\"中添加函数定义

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\"中添加函数实现

////////////////////////////////////////////////////////////////////////////////// // 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) 准备工作:

在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 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 CServerMgrg_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 }

一定要注释掉:_AtlModule.RevokeClassObjects();

5. IOPCServer接口函数实现

本节将详细介绍IOPCServer接口相关函数的实现。 1)准备工作

a. 添加CGlobalLock类

该类包装CRITICAL_SECTION,实现多线程程序中对共享数据成员的保护。这里我们用来实现对opc group list和opc item list的操作的保护。 将下面的code加到stdafx.h里面:

1 extern CRITICAL_SECTION g_globalLock; 2 class CGlobalLock 3 { 4 public:

5 CGlobalLock( ) 6 {

7 m_pCriticalSection = &g_globalLock;

8 EnterCriticalSection( m_pCriticalSection ); 9 } 10

11 CGlobalLock( CRITICAL_SECTION *cs ) 12 {

13 m_pCriticalSection = cs;

14 EnterCriticalSection( m_pCriticalSection ); 15 } 16

17 ~CGlobalLock() 18 {

19 LeaveCriticalSection( m_pCriticalSection ); 20 } 21

22 CRITICAL_SECTION* m_pCriticalSection; 23 };

在\"OPCTestserver.cpp\"里面添加全局变量: CRITICAL_SECTION g_globalLock;

在COPCTestServerApp::InitInstance()中加入: InitializeCriticalSection(&g_globalLock); 在 COPCTestServerApp::ExitInstance(void)中加入: DeleteCriticalSection(&g_globalLock); b.添加COPCGroup类框架

因为在实现IOPCServer::AddGroup函数时要生成COPCGroup对象,所以在这里先生成该类的一个框架,具体实现将在后面章节介绍。

添加C++类,命名COPCGroup,继承IOPCItemMgt接口。

1 #pragma once 2 #include \"opcda.h\" 3

4 class COPCServer; 5

6 class COPCGroup : 7 public IOPCItemMgt 8 { 9 public:

10 COPCGroup(void); 11 ~COPCGroup(void); 12

13 //IUnknown interfaces

14 STDMETHODIMP QueryInterface( REFIID iid, LPVOID* ppInterface); 15 STDMETHODIMP_(ULONG) AddRef( void); 16 STDMETHODIMP_(ULONG) Release( void); 17

18 //IOPCItemMgt Functions 19 STDMETHODIMP AddItems( 20 DWORD dwNumItems, 21 OPCITEMDEF * pItemArray, 22 OPCITEMRESULT ** ppAddResults, 23 HRESULT ** ppErrors 24 ); 25

26 STDMETHODIMP ValidateItems( 27 DWORD dwNumItems, 28 OPCITEMDEF * pItemArray, 29 BOOL bBlobUpdate,

30 OPCITEMRESULT ** ppValidationResults, 31 HRESULT ** ppErrors 32 ); 33

34 STDMETHODIMP RemoveItems( 35 DWORD dwNumItems, 36 OPCHANDLE * phServer, 37 HRESULT ** ppErrors 38 ); 39

40 STDMETHODIMP SetActiveState( 41 DWORD dwNumItems, 42 OPCHANDLE * phServer, 43 BOOL bActive, 44 HRESULT ** ppErrors 45 ); 46

47 STDMETHODIMP SetClientHandles( 48 DWORD dwNumItems, 49 OPCHANDLE * phServer, 50 OPCHANDLE * phClient, 51 HRESULT ** ppErrors 52 ); 53

STDMETHODIMP SetDatatypes( 55 DWORD dwNumItems, 56 OPCHANDLE * phServer,

57 VARTYPE * pRequestedDatatypes,

58 HRESULT ** ppErrors 59 ); 60

61 STDMETHODIMP CreateEnumerator( 62 REFIID riid, 63 LPUNKNOWN * ppUnk ); 65

66 //public members 67 public:

68 LPWSTR m_szName; 69 BOOL m_bActive; 70 DWORD m_dwUpdateRate; 71 OPCHANDLE m_hClientGroup; 72 LONG m_timeBias; 73 FLOAT m_percentDeadband; 74 DWORD m_dwLCID; 75 time_t m_generationTime; 76 COPCServer* m_pServer; 77

78 //private members 79 private:

80 ULONG m_lRefCount; 81 BOOL m_bIsDeleted; 82 }; 83

OPCGroup.cpp:

1 #include \"StdAfx.h\" 2 #include \"OPCGroup.h\" 3

4 COPCGroup::COPCGroup(void) 5 :m_lRefCount(0) 6 {

7 m_szName = NULL;

8 m_timeBias = 300; // Supposedly gotten from TIME_ZONE_INFORMATION. 9 m_dwUpdateRate = 0; 10 m_bActive = TRUE; 11 m_hClientGroup = NULL; 12 m_bIsDeleted = FALSE; 13 m_percentDeadband = (float) 0.0; 14

15 m_pServer = NULL; 16 } 17

18 COPCGroup::~COPCGroup(void) 19 {

20 if( m_szName ) 21 free( m_szName ); 22 } 23

24 // IUnknown::QueryInterface()

25 // This function is the implementation of the standard IUnknown QueryInterface() for the OPC 26 // Sample group class.

27 STDMETHODIMP COPCGroup::QueryInterface( REFIID iid, LPVOID* ppInterface) 28 {

29 if ( ppInterface == NULL) 30 return E_INVALIDARG; 31

32 if( m_bIsDeleted ) 33 return E_FAIL; 34

35 if ( iid == IID_IOPCItemMgt) 36 *ppInterface = (IOPCItemMgt*) this; 37 else

38 *ppInterface = NULL; 39

40 if ( *ppInterface == NULL) 41 return E_NOINTERFACE; 42

43 AddRef(); 44

45 return S_OK; 46 } 47

48 // IUnknown::AddRef()

49 // Standard IUnknown implementation 50

51 STDMETHODIMP_(ULONG) COPCGroup::AddRef( void) 52 {

53 if( m_bIsDeleted ) return E_FAIL; 55

56 return ++m_lRefCount; 57 } 58

59 // IUnknown::Release()

60 // Standard IUnknown implementation 61

62 STDMETHODIMP_(ULONG) COPCGroup::Release( void) 63 {

ULONG currentCount = --m_lRefCount; 65 if ( currentCount == 0 ) 66 {

67 delete this; 68 }

69 return currentCount; 70 } 71

72 ///////////////////////////////////////////////////////////////////////////////////////// 73 // the IOPCItemMgt Functions

74 STDMETHODIMP COPCGroup::AddItems( 75 DWORD dwNumItems, 76 OPCITEMDEF * pItemArray, 77 OPCITEMRESULT ** ppAddResults, 78 HRESULT ** ppErrors 79 ) 80 {

81 return S_OK; 82 } 83

84 STDMETHODIMP COPCGroup::ValidateItems( 85 DWORD dwNumItems, 86 OPCITEMDEF * pItemArray, 87 BOOL bBlobUpdate,

88 OPCITEMRESULT ** ppValidationResults, HRESULT ** ppErrors 90 ) 91 {

92 return S_OK; 93 } 94 95

96 STDMETHODIMP COPCGroup::RemoveItems( 97 DWORD dwNumItems, 98 OPCHANDLE * phServer, 99 HRESULT ** ppErrors 100 ) 101 {

102 return S_OK;

103 } 104 105

106 STDMETHODIMP COPCGroup::SetActiveState( 107 DWORD dwNumItems, 108 OPCHANDLE * phServer, 109 BOOL bActive, 110 HRESULT ** ppErrors 111 ) 112 {

113 return S_OK; 114 } 115 116

117 STDMETHODIMP COPCGroup::SetClientHandles( 118 DWORD dwNumItems, 119 OPCHANDLE * phServer, 120 OPCHANDLE * phClient, 121 HRESULT ** ppErrors 122 ) 123 {

124 return S_OK; 125 } 126 127

128 STDMETHODIMP COPCGroup::SetDatatypes( 129 DWORD dwNumItems, 130 OPCHANDLE * phServer,

131 VARTYPE * pRequestedDatatypes, 132 HRESULT ** ppErrors 133 ) 134 {

135 return S_OK; 136 } 137 138

139 STDMETHODIMP COPCGroup::CreateEnumerator( 140 REFIID riid, 141 LPUNKNOWN * ppUnk 142 ) 143 {

144 return S_OK; 145 } 146

2) 实现IOPCServer::AddGroup

1 STDMETHODIMP COPCServer::AddGroup( 2 LPCWSTR szName, 3 BOOL bActive,

4 DWORD dwRequestedUpdateRate, 5 OPCHANDLE hClientGroup, 6 LONG *pTimeBias, 7 FLOAT *pPercentDeadband, 8 DWORD dwLCID,

9 OPCHANDLE *phServerGroup, 10 DWORD *pRevisedUpdateRate, 11 REFIID riid,

12 LPUNKNOWN *ppUnk 13 ) 14 {

15 if( phServerGroup == NULL || ppUnk == NULL ) 16 return E_INVALIDARG; 17

18 if( pPercentDeadband ) 19 {

20 if( *pPercentDeadband < (float) 0.0 || *pPercentDeadband > (float) 100.0 ) 21 return E_INVALIDARG; 22 } 23

24 //group name

25 CString groupName( szName ); 26

27 //default return parameters 28 *phServerGroup = NULL; 29 *ppUnk = NULL; 30

31 HRESULT hr = S_OK; 32 POSITION pos; 33 COPCGroup* pGroup; 34 LPWSTR pGroupName; 35 36 //lock

37 CGlobalLock globalLock(); 38

39 if( szName == NULL || *szName == (WCHAR) NULL )

40 {

41 // User did not specify a group name, create one for him. 42 pGroupName = (LPWSTR) malloc( 40 ); 43 if( pGroupName == NULL ) 44 {

45 TRACE( \"IOPCServer::AddGroup() - Out of memory, returning E_OUTOFMEMORY\\n\" ); 46 return E_OUTOFMEMORY; 47 }

48 memset( pGroupName, 0, 40 ); 49 CString tempStr;

50 tempStr.Format( \"_Group%d\", m_dwNextGroupNumber++ ); 51 mbstowcs( pGroupName, tempStr, tempStr.GetLength() ); 52 } 53 else {

55 pGroupName = (LPWSTR) malloc( sizeof(WCHAR) * (wcslen(szName) + 1) ); 56 if( pGroupName == NULL ) 57 {

58 TRACE( \"IOPCServer::AddGroup() - Out of memory, returning E_OUTOFMEMORY\\n\" ); 59 return E_OUTOFMEMORY; 60 }

61 wcscpy( pGroupName, szName ); 62 } 63

pos = m_groupList.GetHeadPosition(); 65 while( pos ) 66 {

67 pGroup = (COPCGroup *) m_groupList.GetNext( pos ); 68 if( wcscmp( pGroupName, pGroup->m_szName ) == 0 ) 69 {

70 if( szName == NULL || *szName == (WCHAR) NULL ) 71 {

72 // User didn't specify a group name, but our generated one already exists, so 73 // generate another name. 74 CString tempStr;

75 tempStr.Format( \"_Group%d\", m_dwNextGroupNumber++ ); 76 mbstowcs( pGroupName, tempStr, tempStr.GetLength() + 1 ); 77 pos = m_groupList.GetHeadPosition(); 78 } 79 else 80 {

81 free( pGroupName );

82 TRACE( \"IOPCServer::AddGroup() - Duplicate Group Name, returning OPC_E_DUPLICATENAME\\n\" );

83 return OPC_E_DUPLICATENAME; 84 } 85 } 86 } 87

88 pGroup = new COPCGroup; if (pGroup == NULL) 90 {

91 free( pGroupName );

92 TRACE( \"IOPCServer::AddGroup() - Out of memory, returning E_OUTOFMEMORY\\n\" ); 93 return E_OUTOFMEMORY; 94 } 95

96 pGroup->m_szName = (LPWSTR) malloc( sizeof(WCHAR) * (wcslen(pGroupName) + 1) ); 97 if( !pGroup->m_szName ) 98 {

99 free( pGroupName ); 100 delete pGroup;

101 TRACE( \"IOPCServer::AddGroup() - Out of memory, returning E_OUTOFMEMORY\\n\" ); 102 return E_OUTOFMEMORY; 103 } 104

105 wcscpy( pGroup->m_szName, pGroupName ); 106 free( pGroupName ); 107

108 pGroup->m_bActive = bActive;

109 pGroup->m_hClientGroup = hClientGroup; 110 time(&pGroup->m_generationTime); 111

112 if( dwRequestedUpdateRate == 0 || dwRequestedUpdateRate == 1 ) 113 pGroup->m_dwUpdateRate = MIN_GROUP_UPDATERATE; 114 else if( dwRequestedUpdateRate % MIN_GROUP_INTERVAL == 0 ) 115 pGroup->m_dwUpdateRate = dwRequestedUpdateRate; 116 else

117 pGroup->m_dwUpdateRate = (((int) (dwRequestedUpdateRate / MIN_GROUP_INTERVAL)) + 1) * MIN_GROUP_INTERVAL; 118

119 if( pRevisedUpdateRate )

120 *pRevisedUpdateRate = pGroup->m_dwUpdateRate; 121

122 *phServerGroup = (OPCHANDLE) pGroup; 123

124 if( pTimeBias ) 125 {

126 pGroup->m_timeBias = *pTimeBias; 127 } 128 else 129 {

130 TIME_ZONE_INFORMATION timeZoneInfo; 131

132 if( GetTimeZoneInformation( &timeZoneInfo ) != TIME_ZONE_ID_INVALID ) 133 {

134 pGroup->m_timeBias = timeZoneInfo.Bias; 135 } 136 } 137

138 if( pPercentDeadband ) 139 {

140 pGroup->m_percentDeadband = *pPercentDeadband; 141 } 142

143 pGroup->m_dwLCID = dwLCID; 144 pGroup->m_pServer = this; 145

146 // Get the interface that the client has asked for.

147 if ( FAILED( hr = pGroup->QueryInterface( riid, (void**)ppUnk))) 148 {

149 delete pGroup;

150 TRACE1( \"IOPCServer::AddGroup() - Unknown Interface for Group Object, returning %#8.8x\\n\", hr ); 151 return hr; 152 } 153

1 if( dwRequestedUpdateRate != pGroup->m_dwUpdateRate ) 155 hr = OPC_S_UNSUPPORTEDRATE; 156

157 m_groupList.AddTail( (CObject*) pGroup ); 158

159 return hr; 160 }

其中: //define

#define MIN_GROUP_INTERVAL 10 #define MIN_GROUP_UPDATERATE 1

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- yrrf.cn 版权所有 赣ICP备2024042794号-2

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务