您好,欢迎访问三七文档
COM技术及OPC技术主要内容COM基础知识OPC的概念OPC的作用OPC基础知识实验室OPC组相关的工作一、COM基础知识COM(ComponentObjectModel,组件对象模型)是Microsoft创建并已取得广泛认可的一种组件标准。在COM标准中,COM对象被很好的封装起来,客户无法访问对象的实现细节,提供给用户的唯一的访问途径是通过COM接口来访问。对于COM接口有两方面的含义:首先它是一组可供调用的函数,由此客户可以让该对象做某些事情;其次,接口是组件程序及其客户程序之间的协议。也就是说接口不但定义了可用什么函数,也定义了当调用这些函数时对象要做什么。COM提供了编写组件的一个标准方法,遵循COM标准的组件可以被组合起来以形成应用程序。组件和客户之间通过“接口”来发生联系,至于这些组件是谁编写的、如何实现的都是无关紧要的。IOPCAsyncIO:publicIUnknown{public:virtualHRESULTSTDMETHODCALLTYPERead(/*[in]*/DWORDdwConnection,/*[in]*/OPCDATASOURCEdwSource,/*[in]*/DWORDdwCount,/*[size_is][in]*/OPCHANDLE__RPC_FAR*phServer,/*[out]*/DWORD__RPC_FAR*pTransactionID,/*[size_is][size_is][out]*/HRESULT__RPC_FAR*__RPC_FAR*ppErrors)=0;virtualHRESULTSTDMETHODCALLTYPEWrite(/*[in]*/DWORDdwConnection,/*[in]*/DWORDdwCount,/*[size_is][in]*/OPCHANDLE__RPC_FAR*phServer,/*[size_is][in]*/VARIANT__RPC_FAR*pItemValues,/*[out]*/DWORD__RPC_FAR*pTransactionID,/*[size_is][size_is][out]*/HRESULT__RPC_FAR*__RPC_FAR*ppErrors)=0;virtualHRESULTSTDMETHODCALLTYPERefresh(/*[in]*/DWORDdwConnection,/*[in]*/OPCDATASOURCEdwSource,/*[out]*/DWORD__RPC_FAR*pTransactionID)=0;virtualHRESULTSTDMETHODCALLTYPECancel(/*[in]*/DWORDdwTransactionID)=0;};OPC与COM间关系OPC(OLEforprocesscontrol)是建立在微软公司OLE/COM技术基础上。COM技术的出现为简单地实现控制设备和控制管理系统之间的数据交换提供了技术基础。但如果不提供一个工业标准化的COM接口,各个控制设备厂家开发的COM组件之间的相互连接仍然是不可能的。OPC是作为工业标准定义的特殊的COM接口。对相关COM技术的理解是对OPC技术理解的关键所在。OPC技术还有着它本身的独特性,理解了COM技术只是理解OPC技术的第一步。COM组件的特点遵循COM规范编写的组件具有以下特点:COM组件是以二进制的形式发布,所以COM组件是完全与语言无关的。COM组件可以在不妨碍老客户的情况下被升级。COM提供了一种实现同一组件不同版本的标准方法。升级其实就是在现有的组件上增加新的接口就可以了。COM组件可以透明地在网络上被重新分配位置。对远程机器上的组件同本地机器上的组件的处理方式没有什么差别。COM组件是一种给其他应用程序提供面向对象的API服务的极好方法。COM接口客户程序和组件程序通过接口进行相互之间的通信。组件程序就是通过接口暴露它的功能给客户程序的,而COM客户程序是不可能看见组件对象本身的。仅有接口是可见的,它告诉客户程序能利用组件能干什么,如何利用它的功能。在组件内,接口以虚函数表的形式实现的。实际上,COM标准就是标准的接口和使用它所需协议的描述,所以说接口是COM允许对象跨进程、跨计算机进行交互的关键技术。接口的定义、结构与分类COM对于接口的定义和接口的实现作了严格的区分。通过下面的IUnknown接口可以知道,在接口中只有接口方法的描述,而没有实现。COM接口的名字以字母I打头。其中IUnknown接口最重要,因为所有其它接口都是从IUnknown接口直接或间接继承而来的。IUnkown接口定义了三个方法:1、HRESULTQueryInterface([in]REFIIDriid,[out]void**ppv);2、ULONGAddRef();3、ULONGRelease();COM定义的每一个接口都必须从IUnkown接口继承过来。原因在于IUnkown接口提供了两个非常重要的特性:生存期控制和接口查询。客户程序只能通过接口与COM对象进行通信,虽然客户程序可以不管对象内部实现的细节,但它要控制对象存在与否。如果客户还要继续对对象进行操作,则它必须保证对象一直存在于内存中;如果客户对对象的操作已经完成,以后也不再需要该对象了,则应该及时地把对象释放掉,以提高系统资源的利用率。IUnkown接口中的AddRef()和Release()负责对象引用计数,实现组件对象生命周期的管理。每当COM组件被引用一次就应调用一次AddRef()方法。而当客户端在释放COM组件的某个接口时就需要调用Release()方法。如果一个COM对象实现了多个接口,在初始时刻客户程序不太可能得到该对象的所有接口指针,它只会拥有一个接口指针。如果客户程序需要其它的指针,则利用IUnkown接口中的QueryInterface()方法是用于查询组件对象所实现的其它接口。OPC对象接口定义OPC服务器采用的就是以EXE方式实现的COM组件,它可以运行在本地计算机上,也可以运行在网络上的远程计算机上。实际上就是一个典型的进程外COM组件,只不过OPC服务器的接口是有OPC标准组织规定的标准接口。OPC技术实际上就是COM技术在工业控制中的一个具体的应用。客户/服务器模型客户/服务器模型是一种发展比较成功的软件模型。组件对象和客户程序之间的相互作用是建立在客户/服务器模型的基础之上的,并且COM组件是运行在分布式环境中的。COM不仅仅是简单的客户/服务器模型,有时客户也反过来提供服务,或服务器本身也需要其它对象的一些功能。一个组件对象可能既是服务器也是客户,COM能有效地处理这些情况。在OPC异步通信访问方式中,当OPC服务器触发OPC应用程序的异步访问完成事件时,OPC服务器此时就扮演了客户端的角色,将数据访问结果传送给OPC应用程序。组件存在的类型一般而言,组件具有三种类型:进程内组件、进程外组件和远程组件。第一种是驻留在本地机器上以DLL形式提供,该服务程序被调用时,嵌入到调用程序的线程中运行。此时客户程序和组件程序位于同一台计算机上,客户程序调用组件时,客户程序会把组件程序装入自己的进程空间,即客户程序和组件程序在同一个进程地址空间内。由于它占用和客户端应用程序同样的地址空间,它可以与客户端更快地通信。在客户端和服务器端组件有大量数据转移操作的情况下是最理想的,进程内服务器会更快地装载。第二种是驻留在本地机器上以EXE形式提供,具有独立的进程。客户程序和组件程序也位于同一台计算机上,但客户程序和组件程序分别在不同的进程地址空间中。在COM中,采用了本地过程调用LRC(LocalProcedureCall)来进行本地通信。第三种驻留在远端机器上以EXE形式提供,服务程序通过网络被调用,它在远端机器上运行,结果通过网络返回给调用者。这种功能是使用DCOM实现的。DCOM的优点在于它并不要求任何特别的编程来使其具有功能。另外服务器和客户端通信是通过RRC(RemoteProcedureCall)通信协议进行的。虽然客户程序和组件程序交互的内在方式是完全不同的,但是对于功能相同的进程内和进程外组件,从程序编写的角度看,客户程序是以同样的方法来使用组件程序的。OPC服务器采用的就是以EXE方式实现的COM组件。通过COM库创建COM对象COM库充当了组件程序和客户程序之间的桥梁,在MicrosoftWindows操作系统环境下,这些库以DLL文件的形式存在。在组件对象的创建过程、对象管理、内存管理、以及在标准化操作等方面,都起了重要的作用。COM库可以保证所有的组件按统一的方式进行交互操作,而且它使我们在编写COM时,可不编写为进行COM通信而必需的大量基础代码,而是直接利用COM库的API进行编程,从而大大加快开发的速度。客户程序通过COM库访问组件程序的步骤(1)在进行函数调用以前,必须调用COM库的初始化函数:HRESULT=CoInitialize(NULL);(2)通过函数CLSIDFromProgID()或CLSIDFromProgIDEx()ProgID,查找注册表中相关组件的CLSID。(3)客户端程序调用CoCreateInstance(),创建COM对象,传递组件对象类的CLSID以及所要接口的IID。(4)COM库在HKEY_CLASSES_ROOT\CLSID.键值下查找服务器的CLSID键值,这个键值包含服务器的注册信息。(5)COM库读取服务器的全路径并将组件程序加载。(6)COM库为组件对象类请求类工厂。COM库在类工厂中调用CreateInstance()方法创建客户端程序请求的COM对象。(7)CreateInstance()返回一个接口指针给客户端程序。通过COM库删除COM对象IUnknown是每一个COM对象必须实现的接口,其中有一个Release()方法。调用这个方法通知COM对象你不再需要对象。一旦调用了这个方法之后,就不能再次使用这个接口,因为这个COM对象可能从此就从内存中消失了。如果应用程序使用许多不同的COM对象,因此在用完某个接口后调用Release()就显得非常重要。如果你不释放接口,这个COM对象将保留在内存中,这会增加不必要的开销。如果应用程序要长时间运行,就应该在应用程序处于空闲期间调用CoFreeUnusedLibraries()API函数。这个API函数将卸载任何没有明显引用的COM服务器,因此这也降低了应用程序使用的内存开销。//像上面一样创建COM对象,然后,if(SUCCEEDED(hr)){//通知COM对象不再使用它m_IOPCServer-Release();}应用程序对COM库进行初始化之后,可以调用COM库提供的各种服务,在调用过程中必然要消耗COM库管理的资源。因此,COM程序在完成COM库服务之后,通常在程序退出之前,终止COM库服务函数,以便释放COM库所维护的资源。COM库的终止函数为:voidCoUninitialize(void);凡是调用CoInitialize函数返回S_OK的进程或者程序模块,都一定要调用对应的CoUninitialize函数以保证COM库资源的有效利用。C++调用OPC服务器的关键性代码OPC服务器实际上就是一种COM组件,以下是一个OPC客户程序调用OPC服务器对象的关键性代码,创建一个OPCServer对象的实例并请求指向这个对象m_IOPCServer接口指针。HRESULThr;//首先声明一个接受CoCreateInstance()返回值的HRESULTboolm_bComInitialized;IOPCServer*m_IOPCServer;//指向IID_IOPCServer接口的指针hr=CoInitialize(NULL)//
本文标题:COM及OPC技术
链接地址:https://www.777doc.com/doc-7312715 .html