基于构件的用户自定义事件机制
技术领域
本发明涉及一种计算机运行环境的事件管理机制及装置,尤其是一种基于用户自定义的、实现客户与构件之间交互通信的基于构件的用户自定义事件机制。属于计算机技术领域。
背景技术
C++的编程模型,面向对象的编程,对象链接后不可拆卸,栈不能封装对象,不具有灵活性。构件技术的结构,应用程序通过接口指针访问构件。
现有技术中客户与构件之间的通信过程是单向的,其构件可动态替换。客户创建构件对象,然后客户调用对象所提供的接口函数,在这样的交互过程中,客户总是主动的,而构件对象则处于被动状态。对于一个全面的交互过程来说,这样的单向通信往往不能满足实际的需要。
Microsof t提供了可连接对象技术也可实现构件对客户的调用。但该技术需要用户去实现客户程序与构件对象的连接、事件的激发、接收器的编写等。而且只能以接口为单位注册,即不能为接口中每个成员函数分别注册。另外,Windows应用程序都必须有一个消息循环以处理消息队列中Windows发送过来的消息。这样每个应用程序都有一个等待消息的线程,当同时运行的程序较多时,占系统资源比较大。
COM技术主要解决的问题:不同来源的构件实现互操作,构件升级不影响其他构件、独立于编程语言、构件在进程内、跨进程,甚至跨网络运行的透明度。
发明内容
本发明的目的在于提供一种基于构件的用户自定义事件机制,它能够实现构件端和客户端的交互操作,跨平台的构件开发、运行环境和构件库。
本发明的目的还一在于提供一种基于构件的用户自定义事件机制,可以在操作系统上自动生成中间件(代理构件),提供构件定位、调用、管理、中间件启动生成、构件通信的进程内、跨进程、跨网功能。
本发明的目的又一在于提供一种基于构件的用户自定义事件机制,它能保证软件互操作性、版本升级独立性,具有运行环境透明性全、软件协同开发、软件容错、可靠性、软件复用、软件升级的能力。
本发明的目的再一在于提供一种基于构件的用户自定义事件机制,其具有构件升级的独立性、简单快速的构件互操作、接口重用、本地/远程透明性、编程语言无关性。
本发明的目的另一在于提供一种基于构件的用户自定义事件机制,它自动实现的标准接口类封装层,屏蔽了调用COM构件对象过程的繁琐细节,大大简化了COM客户程序的实现。
本发明通过如下技术方案实现上述目的:一种基于构件的用户自定义事件机制,它包括设置事件管理方、事件发送方,两者通过接口建立关联;事件发送方组织不同参数构成可连接对象事件,可连接对象事件具有接口,用户自定义事件函数接口注册,在事件管理方创建一接收器,将事件函数指针打包设置在事件管理方的接收器内,接收器具有接口,通过注册与可连接对象端连接,把可连接对象接口指针写入对应的接收器内,并把包含事件处理函数指针的接收器所提供的接口指针设置在对应的可连接对象内,在条件符合时,事件发送方激发事件,通过接收器接口,事件管理方回调函数,并解包,执行程序。
具体地,事件发送方的可连接对象事件内设置事件标识,事件管理方的接收器通过接口寻找事件标识,获得该事件连接点对象的连接接口指针。事件处理函数参数中的第一个参数包括该事件接口的类的智能指针,用于标识事件的发送者;第二个及其后的参数与构件定义中的事件参数定义相同。接口包括普通接口和事件接口,其中普通接口为入接口,用于向客户端提供服务,事件接口为出接口,用于事件发生时回调客户端所注册的事件处理函数,对象通过事件接口与客户进行通信,而每一个接口有唯一的标识符,构件添加新的功能,先定义新的接口描述。
当激发事件时,系统将按照是处理函数的注册顺序调用各个事件处理函数。
另外,对于已注册事件,在不需要该事件时可进行注销事件处理,取消该可连接对象事件对应的事件处理函数的连接,具体为可连接对象内取消接收器接口指针,接收器对象被删除(它所保存的事件处理函数指针和可连接对象指针也就没了)。
为实现一对多,或多对一的情况,事件发送方内设置一个以上可连接对象事件,每个事件对应一个可连接对象;事件管理方内可创建一个以上接收器。
为将同一个事件处理函数可以注册到不同对象的事件中,事件管理方接收器可与一个以上的可连接对象建立关系;事件发送方可连接对象可与一个以上事件管理方接收器建立关系,可将同一个事件对应的多个事件处理函数注册,也就是一个事件可对应多个事件处理函数,用于分别执行同一事件的不同注册请求。
为更好地管理可连接对象状态,可连接对象设置有重载处理,用于作为可连接对象处于可调用的状态的“开或关”,管理可连接对象是否能够被调用。
进一步地,在事件管理方第一次注册某可连接对象时,调用重载处理,也就是将可连接对象的调用状态设置为“开”;在事件管理方最后一次注销可连接对象时,调用重载处理,将可连接对象的调用状态设置为“关”;没有重载处理时,执行空操作。
其中,具体地,可连接对象设置连接计数器,用于统计该可连接对象所建立连接的数量,每次多一次注册,计数器加“1”;注销一次,计数器减“1”。当计数器数量为零时,调用重载处理,将可连接对象的调用状态设置为“关”。
事件发送方内设有接口指针容器,用于存储可连接对象事件的描述信息以及接口指针,事件管理方内的接收器注册时,通过接口指针容器寻找所需要的可连接对象事件。这样具体的寻找为枚举方式,逐一寻找事件标识,再连接指针将具体事件对应的事件标识传入,获得该事件连接点对象的连接接口指针。
事件管理方设有与应用程序连接的管理接口,用于接收应用程序的调用应用程序通过该接口把事件处理函数的指针传入事件管理方,事件管理方再去注册该事件处理函数,因为事件管理方的注册、回调等代码是自动生成的,所以需要这个接口与应用程序交互。
基于本发明的基本思想。客户端可为事件管理方或事件发送方;对应的构件端为事件发送方或事件管理方。
本发明具体可用于操作系统;其用于图形系统。系统只在有事件发生时回调用户程序的事件处理函数,不需要消息循环。用户进程可以没有线程,操作系统在有事件发生时再启动线程执行事件处理函数。
本发明还可用于驱动程序。用户程序或操作系统把事件处理函数注册到用事件机制编写的设备驱动程序构件中,当有硬件中断时,驱动程序直接回调用户程序或操作系统的事件处理函数。
综上所述,本发明实现了跨平台的构件开发和运行环境,安全可靠,容错性好,并且小型高效,操作系统支持构件,优化的性能,简单易学,灵活重组。
本发明应用于图形系统,操作系统只在有事件发生时回调用户程序的事件处理函数,不需要消息循环。还可以做到用户进程可以没有线程,操作系统在有事件发生时,再启动线程执行事件处理函数,大大提高了操作系统的效率。
本发明还可用于驱动程序。用户程序或操作系统把事件处理函数注册到用事件机制编写的设备驱动程序构件中。当有硬件中断时,驱动程序直接回调用户程序或操作系统的事件处理函数。这样就可以省去用线程定期查询设备状态的资源。也使程序编写变得更简单。
附图说明
图1为本发明一种系统构成示意图;
图2为本发明一个客户端对应多个构件端的系统构成示意图;
图3为本发明多个客户端对应一个构件端的系统构成示意图;
图4为本发明注册方法流程图;
图5为本发明激发方法流程图;
图6为本发明注销方法流程图;
图7为本发明一种较佳实施例——猜字游戏设置示意图;
图8为本发明一种较佳实施例——猜字游戏激发程序流程图。
具体实施方式
下面结合附图和具体实施例对本发明的技术方案做进一步地说明。
在本发明的自定义事件机制中,完成事件的分发、函数指针的保存、与源对象端的链接以及回调函数等过程。在编写构件程序时,用户只需关心何时激发事件,而在编写客户端程序时,用户只需在适当的时候注册事件处理函数。其它的工作,如事件的分发、回调事件处理函数的过程等都由本发明实现。这样,用户在编写具有事件接口的构件和编写使用该构件的客户端程序都会变得相当简单。
如图1所示,本发明包括一事件管理方—客户端以及一事件发送方—构件端。事件发送方分发事件,事件管理方实现事件处理函数指针的保存、与原对象端的连接、回调函数的过程,两者通过接口建立通信,其中建立通信至少包括用户自定义的接口注册,根据注册信息进行事件激发的步骤,以及用于注销事件处理函数的注销步骤。
客户端可为事件管理方或事件发送方;对应的构件端为事件发送方或事件管理方。
其中每个事件对应一个连接点。
如图1所示,连接点对象记录了包含已注册事件处理函数指针的接收器的接口指针。①:注册事件时保存IDispatch接口指针到连接点对象中;②:注册事件时把标识该连接的dwCookie保存到EventHandler中;③:激发事件时,利用所保存的IDispatch接口指针调用其Invoke方法;④:利用EventHandler所保存的dwCookie注销事件。
一个事件可对应多个事件处理函数,用于分别执行同一事件的不同注册请求。事件处理函数的参数遵循规定:第一个参数必须包括该事件接口的类的智能指针,用于表示事件的发送者;第二个及其后的参数与构件定义中的事件参数定义相同。
事件处理函数还包括重载函数,用于作为可连接对象处于可调用的状态的“开或关”,管理可连接对象是否能够被调用。只有当某事件在客户端第一次注册时调用;只有当某事件在客户端最后一次注销时调用,没有重载时,执行空操作。
事件管理方设置一个以上相互独立的接收器接收器,用于连接接口。事件管理方设有事件管理接口,用于创建或释放事件处理对象。释放事件处理对象保存事件处理函数指针,提供事件管理方接收器的发送接口;事件发送方包括一个以上可连接对象;接收器通过接口通过设定与可连接对象建立连接。事件发送方通过寻找连接指针,将具体事件对应的事件标识传入,获得该事件连接点对象的连接接口指针;
事件发送方事件连接点对象通过连接接口指针与事件管理方接收器的发送接口连接,进行通信。事件发送方设置还有连接指针容器,用于通过事件标识找到对应的连接点。
参见图2,本发明事件管理方接收器作为客户端,可与一个以上的可连接对象建立关系;或如图3所示,事件发送方可连接对象可与一个以上事件管理方接收器建立关系。这样同一个事件处理函数可以注册到不同对象的事件中;同一个事件可以有多个事件处理函数注册在其中。
具体地,接口包括普通接口和事件接口,其中普通接口为入接口,用于向客户端提供服务,,事件接口为出接口,用于事件发生时回调客户端所注册的事件处理函数,对象通过事件接口与客户进行通信。一个构件端可以包含一个或多个普通接口、事件接口。每一个接口有唯一的标识符,构件添加新的功能,先定义新的接口描述。
构件对象的创建、普通接口的调用及注册、注销事件使用类智能指针。
当客户程序需要使用某个事件处理函数响应事件时,需要注册该事件处理函数;客户程序不需要使用某个事件处理函数响应事件时,可将该事件处理函数注销。当激发事件时,系统将按照是处理函数的注册顺序调用各个事件处理函数。
事件发送方是一个可连接对象。每个事件对应一个连接点对象。事件发送提供连接指针容器接口。通过该接口的FindConnectionPoint函数,并传入与具体事件对应的事件标识即可获得该事件连接点对象的连接点接口指针。
事件管理方提供事件管理方接口,可通过该接口创建或释放事件处理器对象。事件处理器对象保存着事件处理函数的指针,并提供管理方接口。
如果一个本发明对象支持一个或多个事件接口,这样的对象称为可连接对象(connectable object),有时也称为源对象。事件接口中每个成员函数代表一个事件。当特定事情发生时,如定时消息或用户鼠标操作发生时,构件对象产生一个事件,客户程序可以处理这些事件。构件对象中事件接口的成员函数并不由对象实现,而是由客户程序来实现。客户程序实现这些事件处理函数,并通过注册把函数指针告诉构件对象,对象在条件成熟时激发事件,回调事件处理函数。
合法智能指针的获取是:经过构件类的操作来创建的,或由合法的智能指针来初始化,或由合法智能指针来赋值的。
较具体地,如图4所示,本发明的客户注册事件处理函数将完成以下操作:
步骤1:获得事件管理方接口指针;
步骤2:通过事件管理方接口创建接收器对象(EventHandler),保存事件处理函数的指针到该对象中;
步骤3:利用源对象提供的连接点容器接口中的寻找连接指针函数找到与该事件对应的连接点对象;
步骤4:通过连接点对象提供的连接点指针接口中的Advise函数把事件接收器提供的管理方接口注册到源对象端;
步骤5:注册时获得标识该连接的dwCookie,保存到接收器对象中。
如图5所示,构件激发事件将完成以下操作:
步骤1:枚举与该事件对应的连接点对象中的每个连接;
步骤2:把事件的参数打包,并对每个连接调用其IDispatch接口中的Invoke函数,以激发事件;
步骤3:接收器对象把传过来的Invoke的参数解包,并通过其保存的函数指针调用事件处理函数。
如图6所示,客户注销事件处理函数将完成以下操作:
步骤1:通过事件处理函数的指针和事件的EID(Event ID事件标识)找到对应的接收器对象;
步骤2:获得接收器对象所保存的标识该连接的dwCookie;
步骤3:利用源对象提供的IConnectionPointContainer接口中的FindConnectionPoint函数找到与该事件对应的连接点对象;
步骤4:通过连接点对象提供的IConnectionPoint接口中的Unadvise函数传入dwCookie作参数,注销事件处理器提供的IDispatch接口;
步骤5:释放接收器对象。
具体实施例一:
参见图7、8,例如创建并管理一猜数字游戏程序的过程。
创建构件对象,得到合法的类智能指针。利用该指针注册事件。该事件设计打印获胜信息,设置退出标志;打印失败信息,设置退出标志;获得正确的数字,打印提示信息。因此在构件端程序需要注册
生成源文件和一个或多个头文件、CPP文件,对应一个头文件和一个CPP文件。
获取4个数字;猜数字,判断结果,触发事件,每次猜数字状态的信息,全中,记录猜的次数。
在编写构件程序时,只需要调用该方法激发事件。
猜数字游戏中,判断出猜数字的结果后,激发TIP事件,发送猜数字状态的信息到客户端,
当猜的数字完全正确时,激发BINGO事件,当完全部都猜错时,激发YOULOSE事件。