BSOPCServer Development - 创建应用程序框架

本文档详细介绍了如何基于VS2008 + SP1创建一个BSOPCServer应用程序框架,包括添加ATL支持以实现OPCServer接口,创建OPCGroup对象,并对IOPCServer接口进行继承和实现。
摘要由CSDN通过智能技术生成

目标:基于单文档程序生成一个程序框架来开发BSOPCServer。

为了方便管理和配置,我们的程序将会基于单文档类型,支持MFC,然后添加ATL支持。添加ATL是为了方便实现OPCServer的接口。

1.1 应用程序类型

这里用的开发环境是VS2008 + SP1。打开创建工程向导,创建基于单文档的应用程序:

clip_image002

由向导生成的文件列表:

clip_image002[6]

1.2 添加ATL支持

我们可以通过添加一个ATL简单对象的办法让开发环境为我们自动添加支持ATL必须的代码。

因为在我们的程序中要有一个server对象实现IOPCServer等接口,这里我们不妨就直接添加一个类COPCServer,继承于IOPCServer:

1) 选择“AddClass …”:

clip_image004

2) 添加“ATL Simple Object”:

各项设置如图所示:

clip_image006

3) 设置线程模型:

线程模型:选择“Apartment”, 即套间模型,表示我们的COPCServer对象运行在套间里保证线程安全;

接口:选择“Custom”, 即定制接口。如果选择“Dual”则表示该对象支持自动化接口,将会继承IDispatch 接口。

聚合: 选择默认值,“允许聚合”,实际上不会用到。

连接点:COPCServer对象需要支持连接点(实现IConnectionPoint接口),但在这里我们不选,我们以后手动加进去。

clip_image008

现在来看看向导为我们添加的几个文件:

1) OPCServer.h

COPCServer类定义的头文件;

2) OPCServer.cpp

COPCServer 类的实现文件;

目前为空文件。

3) OPCServer.rgs

COPCServer 类的注册文件;

应用程序注册时会把该类的相关信息注册到注册表中,这样OPC client就可以根据注册的信息访问到我们的server了。下面我们会专门介绍server的注册。

4) BSOPCServer.idl

接口定义文件;

因为在向导里我们设置COPCServer是继承于IOPCServer的,IOPCServer的定义就在该文件里。我们来看看它的内容:

   1:  import "oaidl.idl";
   2:  import "ocidl.idl";
   3:   
   4:  [
   5:      object,
   6:      uuid(3418B5C9-878F-436B-BFDA-6EB5EEFF4DF2),
   7:      helpstring("IOPCServer Interface"),
   8:      pointer_default(unique)
   9:  ]
  10:  interface IOPCServer : IUnknown{
  11:  };
  12:   
  13:  [
  14:      uuid(B34FC1D6-0D49-4352-B48C-C6C56E856ACA),
  15:      version(1.0),
  16:      helpstring("BSOPCServer 1.0 Type Library")
  17:  ]
  18:  library BSOPCServerLib
  19:  {
  20:      importlib("stdole2.tlb");
  21:      [
  22:          uuid(2C03FF28-FD3C-4B18-9149-5BFFD190BD38),
  23:          helpstring("OPCServer Class")
  24:      ]
  25:      coclass OPCServer
  26:      {
  27:          [default] interface IOPCServer;
  28:      };
  29:  };

文件定义了IOPCServer 接口和BSOPCServerLib类型库。

值得注意的是,因为我们最终要实现OPC标准里定义的IOPCServer接口而不是我们上面自己定义的接口,所以我们一会会把这部分code做一下修改。

编译一下,应该没有错误。

1.3 添加OPCGroup 对象

以同样的方法添加OPCGroup类:

clip_image010

clip_image012

向导生成的文件:

OPCGroup.h —— COPCGroup 类定义头文件

OPCGroup.cpp ——COPCGroup 类实现文件

OPCGroup.rgs ——COPCGroup 类注册文件

同时,相关代码会加到BSOPCServer.idl里面,我们看看都有哪些:

   1:  import "oaidl.idl";
   2:  import "ocidl.idl";
   3:   
   4:  [
   5:      object,
   6:      uuid(3418B5C9-878F-436B-BFDA-6EB5EEFF4DF2),
   7:      helpstring("IOPCServer Interface"),
   8:      pointer_default(unique)
   9:  ]
  10:  interface IOPCServer : IUnknown{
  11:  };
  12:  [
  13:      object,
  14:      uuid(60948577-318D-46F9-948C-838DB34EF8EC),
  15:      helpstring("IOPCGroup Interface"),
  16:      pointer_default(unique)
  17:  ]
  18:  interface IOPCGroup : IUnknown{
  19:  };
  20:  [
  21:      uuid(B34FC1D6-0D49-4352-B48C-C6C56E856ACA),
  22:      version(1.0),
  23:      helpstring("BSOPCServer 1.0 Type Library")
  24:  ]
  25:  library BSOPCServerLib
  26:  {
  27:      importlib("stdole2.tlb");
  28:      [
  29:          uuid(2C03FF28-FD3C-4B18-9149-5BFFD190BD38),
  30:          helpstring("OPCServer Class")
  31:      ]
  32:      coclass OPCServer
  33:      {
  34:          [default] interface IOPCServer;
  35:      };
  36:      [
  37:          uuid(7E67188C-27CA-47E8-BB92-C22BD88272E2),
  38:          helpstring("OPCGroup Class")
  39:      ]
  40:      coclass OPCGroup
  41:      {
  42:          [default] interface IOPCGroup;
  43:      };
  44:  };

可以看到多了IOPCGroup 和 coclass OPCGroup的定义。因为我们将不对其他程序暴露OPCGroup对象,所以删掉OPCGroup.rgs并注释掉BSOPCServer.idl中关于OPCGroup的代码:

[

object,

uuid(60948577-318D-46F9-948C-838DB34EF8EC),

helpstring("IOPCGroup Interface"),

pointer_default(unique)

]

interface IOPCGroup : IUnknown{

};

[

uuid(7E67188C-27CA-47E8-BB92-C22BD88272E2),

helpstring("OPCGroup Class")

]

coclass OPCGroup

{

[default] interface IOPCGroup;

};

也就是说,我们虽然用向导生成了CCOPCGroup类的框架,但我们只保留了OPCGroup.h 和OPCGroup.cpp。

我们还需要对CCOPCGroup类定义进行修改:

在OPCGroup.h文件中注释掉:

1) public CComCoClass<COPCGroup, &CLSID_OPCGroup>,

2) public IOPCGroup

3) DECLARE_REGISTRY_RESOURCEID(IDR_OPCGROUP)

4) COM_INTERFACE_ENTRY(IOPCGroup)

5) OBJECT_ENTRY_AUTO(__uuidof(OPCGroup), COPCGroup)

1.4 继承IOPCServer

上面我们提到虽然我们自己利用向导生成了IOPCServer的定义,但是最终我们用到的是OPC标准里面定义的IOPCServer, 所以我们要把它替换掉。

1) 添加OPC 标准的include文件

OPC基金会为我们提供了一些开发OPC server的公共头文件和idl接口定义文件,为了便于使用,我们把它们拷贝到我们的工程目录下面。 上面提到的IOPCServer接口就在opcda.idl里面定义:

clip_image002[1]

2) 修改BSOPCServer.idl文件

a. 添加import “opcda.idl”;

b. 注释掉IOPCServer的定义:

[
object,

uuid(3418B5C9-878F-436B-BFDA-6EB5EEFF4DF2),

helpstring("IOPCServer Interface"),

pointer_default(unique)

]

interface IOPCServer : IUnknown{

};

c. 设置编译BSOPCServer.idl包含的路径:

(opcda.idl 跟BSOPCServer.idl 不在一个文件夹下面。)

clip_image004[1]

重新编译,在编译OPCServer.cpp时会得到如下错误提示:

c:/program files/microsoft visual studio 9.0/vc/atlmfc/include/atlcom.h(1867) : error C2259: 'ATL::CComObject<Base>' : cannot instantiate abstract class

这个错误主要是因为我们把COPCServer从IOPCServer继承,但是没有实现IOPCServer定义的方法。

在OPCServer.h里添加IOPCServer接口函数定义:

// IOPCServer implementation methods

STDMETHODIMP AddGroup(
    LPCWSTR szName,
    BOOL bActive, 
    DWORD dwRequestedUpdateRate, 
    OPCHANDLE hClientGroup,
    LONG* pTimeBias, 
    FLOAT* pPercentDeadband, 
    DWORD dwLCID, 
    OPCHANDLE* phServerGroup,
    DWORD* pRevisedUpdateRate, 
    REFIID riid, 
    LPUNKNOWN* ppUnk);

STDMETHODIMP GetErrorString(HRESULT dwError, LCID dwLocale, LPWSTR* ppString);

STDMETHODIMP GetGroupByName(LPCWSTR szName, REFIID riid, LPUNKNOWN* ppUnk);

STDMETHODIMP GetStatus(OPCSERVERSTATUS** ppServerStatus);

STDMETHODIMP RemoveGroup(OPCHANDLE hServerGroup, BOOL bForce);

STDMETHODIMP CreateGroupEnumerator(OPCENUMSCOPE dwScope, REFIID riid, LPUNKNOWN* ppUnk);

在OPCServer.CPP文件添加接口函数实现,这里我们没有具体实现每个函数,只是设置返回值:

// IOPCServer implementation methods

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::GetErrorString(HRESULT dwError, LCID dwLocale, LPWSTR* ppString)
{
    return S_OK;
}

STDMETHODIMP COPCServer::GetGroupByName(LPCWSTR szName, REFIID riid, LPUNKNOWN* ppUnk)
{
    return S_OK;
}

STDMETHODIMP COPCServer::GetStatus(OPCSERVERSTATUS** ppServerStatus)
{
    return S_OK;
}

STDMETHODIMP COPCServer::RemoveGroup(OPCHANDLE hServerGroup, BOOL bForce)
{
    return S_OK;
}

STDMETHODIMP COPCServer::CreateGroupEnumerator(OPCENUMSCOPE dwScope, REFIID riid, LPUNKNOWN* ppUnk)
{
    return S_OK;
}

重新build成功。

到此为止,应用程序框架已经生成,接下来我们来探讨OPC server的注册问题。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值