




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、第7章 客户程序的C+映射n接口映射 在客户端生成一个代理,代理类向客户程序提供一个定位透明的接口,由IDL定义所生成,每一个IDL接口都会生成一个单独的C+代理类。 (1) 生成的代理类与IDL中定义的接口名相同 (2) 代理类由CORBA:Object继承得到 (3) 代理类提供了一个与IDL中定义的操作相对应的一个同名方法。 (4) 此方法被说明为纯虚拟函数,此代理类是不能被实例化的抽象基类。 如果客户程序中有MyObject代理类的一个派生的实例,并且客户程序调用了get_value方法,那么ORB将向目标对象发送一条消息。客户端的代码将被封闭,直到方法返回并且传送其运行结果。 因为代
2、理类是一个抽象基类,客户程序不能直接创建它的实例。即使 ORB不生成抽象的代理类,也必须把他们当作抽象类来处理。 客户不允许直接创建代理的实例,只有当对象引用进入客户程序的地址空间时,才可以由ORB创建代理的实例。客户程序不直接对代理进行操作。客户程序可以通过句柄,也就是对象引用类型来访问代理类的实例。客户程序的C+映射n对象引用类型 (1) MyObject-这是一个代理基类 (2) MyObject_ptr-这是一个原始的对象引用类型,类似于C+类的实例指针 (3) MyObject_var可以被作为代理的句柄,它与MyObject_ptr非常相似,只是增加了内存管理。n对象引用的生命周期
3、 (1) 当对象引用进入客户程序的地址空间时,有客户端的ORB代表客户程序创建代理。ORB向客户程序返回一个指向新代理的_ptr引用。 (2) 客户程序可以撤消引用 (3) 客户程序可以创建引用所保存的拷贝。 (4) 客户程序可以创建一个空引用。n删除引用 MyObject_ptr mop=; CORBA:release(mop)n引用拷贝 MyObject_ptr mop1=MYObject:_duplicate(mop);_ptr引用的语义n代理与_ptr引用的映射 在生成代理类的同时就会生成_ptr引用。_ptr引用必须被当作C+指针来使用。n继承与扩展 _ptr引用是指向相应代理类的C
4、+指针,_ptr支持隐式扩展,即指向派生类的指针可以赋给指向基类的指针。 _ptr引用之间的普通赋值是浅赋值。对引用计数不会产生影响。n紧缩转换 在C+中,拒绝把指向基类的指针赋值给指向派生类的指针。强制转换是错误的。n类型安全的紧缩 可以用_narrow来进行安全的强制类型向下转换,与需要的类型相匹配时,返回非空引用,不匹配则返回空引用。_narrow与C+中的dynamic_cast非常相似,作用相同。_ptr引用的语义n非法使用_ptr引用 (1) 进行相等或不等的比较 (2) 对引用使用关系运算符: (3) 对引用使用算术运算符 (4) 将_ptr引用转换为void *,或将void
5、*转换为_ptr (5) 不采用_narrow进行向下强制类型转换,ORB的初始化n1. 用ORB_init来对ORB进行初始化 ORB_ptr ORB_init( int & argc, char* argv, const char* orb_identifier=“”); argc是argv中的输入项个数 argv是传递给main的命令行参数向量 orb_identifier是由供应商指定的字符串(缺省情况下为空字符串)。初始引用nORB接口包含了两个可以用来创建和获取初始引用的操作 object_to_string 将引用转换为一个可以打印的字符串 string_to_objec
6、t 将字符串转换为对象引用,可以返回任意类型的引用,此操作创建一个新的代理,因此在最后要调用release再次将引用释放。对象伪接口n伪接口:用PIDL调用的接口,不一定由Object隐式继承,不能作为参数传递给普通接口,不能被动态调用,在接口库中没有定义,有一种不同于普通规则的用于特殊目的的语言映射。n_is_a操作 用来测试对象引用是否支持由仓库id参数所支持的接口。 obj-_is_a(“IDL: 同_narrow相似,都用来测试引用是否支持某个接口。而_is_a不需要在编译时知道接口信息,_narrow需要;_is_a用于DII。n_non_existent 用来测试引用是否标识一个已
7、有的对象。与Ping操作相类似。 Ping操作用来测试与实现的一个对象的服务器程序是否可以联系上。 _non_existent为了作出判断,可能会与实现对象的服务器程序进行联系,并且可能会激活该服务器程序,可以用Ping来进行联系和激活。对象伪接口n_is_equivalent 用来测试一个引用与另一个引用是否完全一样。如果返回true,则表明两个引用完全相同,返回false,则表示可能相同,也可能不同。此操作必须是高效的,因此只能在本地实现n_hash 用来测试引用集合。如果两个引用返回不同的散列值,则表示引用肯定时不同的n_is_nil 用来测试一个引用是否为空_var引用n_var引用的
8、映射 _var引用的映射与String_var的映射非常相似。对于每个IDL接口,编译器不仅生成接口类和_ptr类型,而且添加了一个_var类。其中的操作与String_var类似。 用_ptr给_var进行初始化或赋值,是一个浅赋值。 用一个_var对另一个_var进行初始化或赋值,是一个深赋值。n_var引用与扩展 不允许通过其它的_var类型对它们进行隐式的初始化或扩展赋值。必须显式的调用_duplicate。n同时使用_var和_ptr引用 _var引用可以转变为指针引用,因此可以进行从派生_var类到基_ptr类的扩展赋值。此赋值是浅赋值。n篏套在用户定义类型中的引用 引用篏套在用户
9、定义类型内,就需要使用_mgr引用。参数传递规则n参数传递规则主要是为了考虑位置透明性和高效性来制定的。n位置透明性:相同还是不同地址空间,参数的内存管理规则必须统一。这一条件允许相同的源代码用于被配置在一起的对象和远程对象。在此需要用到某些内存管理规则,如变长度的out参数必须由被调用的函数来分配,并且由调用程序来释放。n高效性:要尽可能避免参数值的拷贝。通过对象引用来调用被配置在同一地址空间的CORBA对象几乎与通过虚拟函数来调用C+对象一样快。在此要求大的数值应该由引用来传递,而不是数值。n定长度类型和变长度类型 定长度类型: 整数类型;浮点数类型;定点数类型;字符类型;boolean;
10、octet;枚举类型。 变长度类型: string和wstring;对象引用;any类型;序列类型 结构、联合和数组是变长还是定长主要是看他们包含的元素类型。参数传递规则n生成的_out类型 out参数往往采用正式的参数类型typename_out。如long类型的out参数,正式类型为CORBA:Long_out。这是因为对于定长度类型和变长度类型的out参数,所使用的内存管理规则不一样。 对于定长度类型,生成的_out类型只是引用的类型定义。例如,Long_out在CORBA名字空间中定义如下: typedef Long & Long_out 对于变长度类型,生成的_out类型是一
11、个类。如String_out在名字空间中定义为一个类: class String_out; 原因在于内存管理规则。变长度类型由被调用的函数进行内存分配,并且为变长度类型生成的_out类可以确保内存被正确释放。参数传递规则n简单类型的参数传递 简单类型由数值方式还是引用方式来传递取决于被调用函数是否可以修改参数。 in参数采用值传递的方式,它的值不会改变。 inout和out参数采用引用方式传递,因为在调用过程中可能会修改它的值。Long_out是Long&的一个别名。n复杂的定长度类型的参数传递 复杂的基本和简单类型的传递相似。只是由于效率方面的原因,in参数通过指向const类型的引
12、用方式来传递。Const Fls & fls_inn包含定长度元素的数组的参数传递 因为C+不允许通过数值方式来传递数组,因此存根中使用了数组的指针。 Typedef double Darr3 virtual Darr_slice* darr_op const Darr darr_in, Darr_slice * darr_inout, Darr_out darr_out);Darr_slice *表示指向元素类型的指针。参数传递规则nIn参数darr_in使用了正式的参数类型const Darr。根据C+缺省转换规则,这与把参数类型说明为const CORBA:Double *是一回
13、事, const CORBA:Double *事指向常量数组的指针类型。n调用程序将传递指向第一个元素的指针,这样就允许被调用函数通过指针来改变由调用程序分配的数组。n返回的数值也是一个指针,返回数值由被调用函数来分配,必须由调用程序来释放。因此必须在程序最后将函数返回值释放掉。必须使用生成的内存释放函数Darr_free来释放返回的数组。变长度参数的内存管理Person_var p=;char * s;s=p-name();string_free(s);while (!done)op=get_request();char * s;s=invoke(op);send(s)CORBA:strin
14、g_free(s);char * name()p-invoke(“name”);unsigned len;len=recv_len();s=string_alloc(len);recv(s);return s;char * name() char * s; s=string_dup(); return s;RequestReply返回一个变长度值返回一个变长度值远程情况下远程情况下ClientServer变长度参数的内存管理n在变长度类型时,在服务器和客户程序之间关系如下:n接口如下定义: interface Person string name();n客户程序如下: Person_var p
15、=; char s*; s=p-name(); / CORBA:string_free(s);当客户程序调用name方法时,它将调用代理对象的一个成员函数。事件的顺序如下:(1) 代理的name成员函数创建一个包含操作名称、对象密钥和操作的in和inout参数(这里没有)的请求。(2)代理成员函数把请求写到服务器程序的连接中,并立即调用连接中阻塞读取的操作(在此是recv_len)。运行时的客户端程序将阻塞,直到收到服务器程序的应答为止。变长度参数的内存管理(3) 此时,请求将通过网络传输给服务器程序。服务器程序将阻塞在get_request操作中,等待客户端连接收到请求。(4) 客户程序得到
16、外来请求后将继续执行get_request,通过它来获取操作名与对象密钥。(5) 运行时的服务器程序调用一个普通的invoke函数,其中的一个参数是操作名。Invoke通过操作名来标识正确的应用程序成员函数,以调用应用程序代码。(6) 现在,控制权移交给服务器端的由应用程序提供的name函数。Name函数通过string_dup来分配和初始化字符串的内存,并且返回指向这个内存缓冲区的指针。(7) 控制权又移交给服务器端的运行时ORB,并且需要运行时ORB传递一个指向已分配过的字符串的指针。现在,运行时ORB构造一个包含字符串拷贝的应答,并且将这个应答发给客户程序。变长度参数的内存管理(8) 服
17、务器端的运行时ORB调用string_free来释放这个字符串。(因为字符串的内容已经发送给了客户程序)(9) 现在,服务器端的运行时ORB已经完成了调度循环中的一次循环,它将再次调用get_request,直到下一个客户请求到来后,才能继续下面的操作。(10) 同时,应答通过网络传递给客户程序,客户程序将执行recv_len下面的操作。返回值是一个字节计数器,用来表示字符串的长度。(11) 客户端的运行时ORB调用string_alloc来创建一个包含len字节的缓冲区,并且调用recv,以便将字符串内容读到缓冲区中。(12) 返回一个指向包含字符串的缓冲区的指针后,客户端的存根将结束。(1
18、3) 现在,控制权移交给使用字符串的应用程序代码,应用程序在最后将通过调用string_free擦字符串释放掉。变长度参数的内存管理n这里应该注意,客户程序或服务器程序中都没有内存泄漏现象: (1) 在服务器端,应用程序调用string_alloc,框架中生成的代码将在把字符串发送给客户程序后,调用string_free。 (2) 在客户端,生成的存根代码将调用string_alloc,并且向应用程序代码返回一个指向字符串的指针,string_free在应用程序中被调用。变长度参数的内存管理Person_var p=;char * s;s=p-name();string_free(s);cha
19、r * name() char * s; s=string_dup(); /Fill string return s;返回一个变长度值返回一个变长度值配置在一起的情况配置在一起的情况变长度参数的内存管理n配置在一起的情况下,和前面一样,客户程序调用它的代理的name成员函数。然而,现在对于客户程序的地址空间而言,这个成员函数是本地的,因此没有必要检查所有与网络有关的代码。n注意:配置客户程序与服务器程序时,不需要改变应用程序源代码。最重要的时内存规则没有改变。服务器程序调用string_alloc,客户程序调用string_free,因此这里不会出现内存的泄漏。n远程调用和配置在一起调用的透明
20、性是变长度参数内存管理规则的核心。变长度参数的传递要遵循此规则,用于返回值的规则同样也适用于inout参数和out参数。n注意:在发送端分配一个变长度值,而在接收端将它释放掉。字符串和宽位字符串的参数传递字符串和宽位字符串的参数传递nin参数作为const char *类型来传递。字符串调用程序进行内存的分配、初始化和释放。ninout参数作为char * &类型来传递,也由调用程序进行内存分配和初始化。必须用string_alloc或string_dup进行动态内存分配。因此字符串长度可能不同,就需要进行再次分配内存,因此inout参数被作为引用(而不是一个指针)传递给一个指针。nO
21、ut参数作为CORBA:string_out类来传递,它是一个类,它的构造函数中有一个参数的类型是char* &,而不是一个类型,它被设置为代理分配的字符串的地址,这也就是为什么要传递一个指向指针的引用(代理必须设置指针的值,而不仅仅是指针指向的字节)。调用程序只对最终由string_free释放的字符串负责。n返回值与out参数相似。代理对字符串内存分配和初始化,调用程序最终释放。n宽位字符串一样,只是用wstring而已。参数传递规则的小结IDL类型类型ininoutout返回类型返回类型SimpleSimpleSimple&Simple&SimpleEnumEnu
22、mEnum&Enum&EnumFixedConst fixed &Fixed &Fixed &FixedStringConst char *char *&char *&char *WstringConst wchar *Wchar *&Wchar *&Wchar *AnyConst any &Any &Any * &Any *ObjrefObjref_ptrObjref_ptr &Objref_ptr &Objref_ptrSequenceConst sequence&Seq
23、uence &Sequence * &Sequence *Struct,fixedConst struct&struct&struct&structUnion,fixedConst union&union&union&unionArray,fixedConst arrayArray_slice*Array_slice*Array_slice*Struct,variableConst struct&struct&struct *&struct* Union,variableSonst union&un
24、ion&Union *&Union *Array,variableConst arrayArray_slice*Array_slice*&Array_slice*使用_var类型来传递参数IDL类型类型ininout/out返回返回StringConst String_var &String_var &String_varWstringConst Wstring_var &Wstring_var &Wstring_var AnyConst Any_var &Any_var &Any_varObjrefConst objre
25、f_var &objref_var &objref_varSequenceConst sequence_var &sequence_var &sequence_varStructConst struct_var &struct_var &struct_varUnionConst union_var &union_var &union_varArrayConst array_var &array_var &array_var使用使用_var类型的参数传递规则类型的参数传递规则参数传递的陷阱n传递空指针 在IDL接口之
26、间传递空指针在C+映射中是非法的。因为IDL并不支持空指针的概念;如果C+映射允许传递空指针的话,那么就会破坏CORBA的语言透明性,因为有些语言不支持指针。n传递未初始化的in或inout参数 在传递未初始化的字符串和联合时,因为字符串被映射为char *类型,传递一个未初始化的字符串易破坏程序;编组代码或者会间接引用一个空指针,或者会间接引用一个无用指针。如果传递一个缺省的构造的String_var,那么就会传递一个空指针。然而,传递一个篏套的未初始化的字符串是安全的,因为篏套的字符串可以初始化为一个空字符串。 联合也一样,在C+映射中,在IDL接口之间传递一个未初始化的联合是非法的。参数
27、传递的陷阱n忽略变长度的返回值 如果使用_var类型代码是不会造成内存泄漏的,然而必须记住,一定要捕获返回变长度值的操作的返回值。n忘记释放编程度的out参数 必须释放变长度的out参数,除非使用了_var类型,建议要养成使用out参数的_var类型的习惯。服务器端C+映射n用来实现和表示CORBA对象的编程语言实体称为伺服程序(servant)。由于伺服程序为CORBA对象提供了函数体,因此它们使CORBA对象具体化。n在CORBA中,对象适配器把CORBA对象链接到编程语言的伺服程序上,从概念上讲,对象适配器是在ORB和编程语言的伺服程序之间的媒介,它们为创建CORBA对象和CORBA对象
28、的对象引用,以及为调度合适的伺服程序请求提供了服务。POA提供了编程语言的伺服程序在由不同厂家提供的ORB之间的可移植性。一个伺服程序可能包含多个POA实例,以便支持不同特性的CORBA对象,或支持多种伺服程序的实现类型。可是至少有一个为名Root POA的POA,即根POA。n客户发送请求,服务器程序的ORB接收请求,在发送给POA,并在POA中创建目标对象。然后,POA再次调度请求给实现目标对象的伺服程序。伺服程序则执行请求,并返回out和返回值。服务器端C+映射ORBPOAManagerPOAServantsdispatchServer ApplicationIncomingreques
29、tORB、POA管理器、POA和伺服程序间的关系服务器端C+映射n与IDL接口相对应的服务器端C+类被称为框架类。与客户端的代理类相对应,并且由IDL编译器在C+源文件中生成,这些源文件被编译到应用程序中。与框架类的客户端副本不同的是,框架类用来当作特定应用程序类的基类。框架只为CORBA对象实现提供一个支撑架构或框架。通过从这些框架类中派生伺服类,应用程序可以扩充并完成框架的架构,以便用于CORBA对象的创建和实现。接口的映射n服务器端C+映射为每个IDL接口生成一个单独的框架类。IDL编译器通常生成包含框架类定义的头文件,同时还要生成一个实现文件。 interface MyObject;
30、生成的头文件中包含下面的框架类定义: class POA_MyObject;注意:(1) 只有最外层的作用域名称才使用POA_前缀。(2) 框架类由PortableServer:ServantBase继承得到, PortableServer:ServantBase是所有框架类共同的基类。(3) 框架类提供一个与IDL的操作相对应的方法(4) 此方法被说明为纯虚函数,因此不能实例化抽象基类。(5) 方法中包含了一个异常说明,这个异常说明用来限制此方法能发送C+异常的类型。CORBA:SystemException基类包含所有框架类的异常说明。伺服类n为了创建MyObject类型的一个CORBA对
31、象,必须从POA_MyObject类中派生一个伺服类,并且实现所有的纯虚拟方法。n假设编写一个IDL为my_object.idl文件,对此编译。(1) 建立伺服类时要包含生成的服务器端头文件my_objectS.hh,在my_object.idl文件中包含了接口的定义,包含这个头文件是为了获取POA_MyObject基类的说明。(2) 伺服类的名称MyObject_impl的选择完全由程序决定,符合习惯,使用_impl后缀。 (3) MyObject_impl类由POA_MyObject框架类继承得到,并且重载了纯虚函数get_value。这就使得MyObject_impl成为一个可以实例化的
32、具体类。 (4) 必须在自己的伺服类中实现所有继承得到的纯虚函数,否则,不允许创建伺服类实例。也可以假如任何对支持伺服类的实现有用的东西。例如:构造函数、析构函数、附加的成员函数,或数据成员等。在实际应用中,很少需要对伺服程序进行赋值或赋值,因此建立隐藏伺服程序的拷贝构造函数和缺省的赋值运算符。可以把其放在private:中来实现隐藏。对象的实体n为了通过MyObject_impl伺服类的一个实例来使CORBA对象具体化,必须创建一个MyObject_impl伺服程序和一个CORBA对象,并把伺服程序注册为CORBA对象的实体。 MyObject_impl servant(42);/创建一个伺
33、服程序实例,在此只是一个C+对象,并没有建立伺服程序和CORBA对象之间的连接。 MyObject_var object=servant._this();/创建一个CORBA对象,用创建的伺服程序来具体化这个对象。在此调用伺服程序的_this函数过程隐式执行了: (1) 在Root POA下创建一个CORBA对象。 (2) 用Root POA把伺服程序注册为新对象的实现。 (3) 为新对象创建一个对象引用。 (4) 返回新的对象引用。 对象的实体 _this函数由框架类提供。POA_MyObject类中包含了由IDL编译器生成的_this成员函数。 对于任何表示IDL接口A的框架类POA_A,
34、POA_A:_this函数的返回值都是A_ptr,即接口A的C+对象引用类型,因为调用_this的程序负责确保最终会对返回的对象引用调用CORBA:release,在此可以把这个返回值返回给A_var,它将负责释放。 由_this创建的CORBA对象是一个暂态对象。暂态CORBA对象在POA中创建,并且受该POA生命周期的限制。可以用合适的策略来创建伺服程序的POA,_this就能提供这种形式的创建和注册服务。Root POA支持的策略的标准设置已经被显示设计为允许提供这种方式来使用_this。服务器程序的main函数n在完成服务器应用程序时,必须完成下面这些步骤。 (1) 提供标准的CORBA:ORB_init调用初始化ORB (
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 新西兰食堂管理办法
- 团队建设费管理办法
- 士官生教官管理办法
- 在职工活动管理办法
- 品生产许可管理办法
- 机场租赁物管理办法
- 员工敬业度管理办法
- 新能源船舶管理办法
- 协统员资金管理办法
- 小区安保类管理办法
- 2025至2030年中国油页岩行业市场竞争格局及发展前景研判报告
- 2025至2030中国工业软件行业项目调研及市场前景预测评估报告
- 心肺复苏的试题及答案
- 妇科专业疾病临床诊疗规范2025年版
- 贷款渠道签约协议书
- 2025芜湖事业单位笔试真题
- 家人吵架和解协议书
- 广西壮族自治区南宁市青秀区第二中学2025年数学八下期末调研试题含解析
- 2025中国中式餐饮白皮书
- 通信材料采购合同协议
- 建筑工程进度情况汇报范文
评论
0/150
提交评论