5. IOPCServer接口函数实现

     本节将详细介绍IOPCServer接口相关函数的实现。

     1)准备工作
     a.  添加CGlobalLock
     该类包装CRITICAL_SECTION,实现多线程程序中对共享数据成员的保护。这里我们用来实现对opc group list和opc item list的操作的保护。

     将下面的code加到stdafx.h里面:

ContractedBlock.gif ExpandedBlockStart.gif Code
 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接口。

ContractedBlock.gif ExpandedBlockStart.gif Code
 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 
54     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
64         );
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:

 

ContractedBlock.gif ExpandedBlockStart.gif Code
  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 = (float0.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 )
 54         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 {
 64     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,
 89                                       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

     

ContractedBlock.gif ExpandedBlockStart.gif Code
  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 < (float0.0 || *pPercentDeadband > (float100.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, 040 );
 49         CString tempStr;
 50         tempStr.Format( "_Group%d", m_dwNextGroupNumber++ );
 51         mbstowcs( pGroupName, tempStr, tempStr.GetLength() );
 52     }
 53     else
 54     {
 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 
 64     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;
 89     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 
154     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

(未完待续)

posted on 2008-10-07 14:37  CheneySHI 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/opc521/archive/2008/10/07/1305528.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值