资源预览内容
第1页 / 共56页
第2页 / 共56页
第3页 / 共56页
第4页 / 共56页
第5页 / 共56页
第6页 / 共56页
第7页 / 共56页
第8页 / 共56页
第9页 / 共56页
第10页 / 共56页
亲,该文档总共56页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
第7章 客户程序的C+映射n接口映射在客户端生成一个代理,代理类向客户程序 提供一个定位透明的接口,由IDL定义所生 成,每一个IDL接口都会生成一个单独的 C+代理类。(1) 生成的代理类与IDL中定义的接口名相同(2) 代理类由CORBA:Object继承得到(3) 代理类提供了一个与IDL中定义的操作相 对应的一个同名方法。(4) 此方法被说明为纯虚拟函数,此代理类是 不能被实例化的抽象基类。 客户程序的C+映射n对象引用类型(1) MyObject-这是一个代理基类(2) MyObject_ptr-这是一个原始的对象引用类型 ,类似于C+类的实例指针(3) MyObject_var可以被作为代理的句柄,它与 MyObject_ptr非常相似,只是增加了内存管理。n对象引用的生命周期(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+指针, _ptr支持隐式扩展,即指向派生类的指针 可以赋给指向基类的指针。 _ptr引用之 间的普通赋值是浅赋值。对引用计数不 会产生影响。n紧缩转换在C+中,拒绝把指向基类的指针赋值给指 向派生类的指针。强制转换是错误的。n类型安全的紧缩可以用_narrow来进行安全的强制类型向下 转换,与需要的类型相匹配时,返回非空 引用,不匹配则返回空引用。_narrow与 C+中的dynamic_cast非常相似,作用相同 。_ptr引用的语义n非法使用_ptr引用(1) 进行相等或不等的比较(2) 对引用使用关系运算符:(3) 对引用使用算术运算符(4) 将_ptr引用转换为void *,或将void *转换为_ptr(5) 不采用_narrow进行向下强制类型转换,ORB的初始化n1. 用ORB_init来对ORB进行初始化ORB_ptr ORB_init(int argc是argv中的输入项个数argv是传递给main的命令行参数向量orb_identifier是由供应商指定的字符串(缺省情况下为空 字符串)。初始引用nORB接口包含了两个可以用来创建和获取初始引用的 操作object_to_string将引用转换为一个可以打印的字符串string_to_object将字符串转换为对象引用,可以返回任意类型的引用, 此操作创建一个新的代理,因此在最后要调用release再 次将引用释放。对象伪接口n伪接口:用PIDL调用的接口,不一定由Object隐式继承,不能作 为参数传递给普通接口,不能被动态调用,在接口库中没有定义 ,有一种不同于普通规则的用于特殊目的的语言映射。n_is_a操作用来测试对象引用是否支持由仓库id参数所支持的接口。obj-_is_a(“IDL:acme.com/CCS/Contorler.1.0”)同_narrow相似,都用来测试引用是否支持某个接口。而_is_a不需要 在编译时知道接口信息,_narrow需要;_is_a用于DII。n_non_existent用来测试引用是否标识一个已有的对象。与 Ping操作相类似。Ping操作用来测试与实现的一个对象的服务 器程序是否可以联系上。_non_existent为了作出判断,可能会与实现 对象的服务器程序进行联系,并且可能会 激活该服务器程序,可以用Ping来进行联系 和激活。对象伪接口n_is_equivalent用来测试一个引用与另一个引用是否完全一样。如果返 回true,则表明两个引用完全相同,返回false,则表示 可能相同,也可能不同。此操作必须是高效的,因此 只能在本地实现n_hash用来测试引用集合。如果两个引用返回不同的散列值, 则表示引用肯定时不同的n_is_nil用来测试一个引用是否为空_var引用n_var引用的映射_var引用的映射与String_var的映射非常相似。对于每个 IDL接口,编译器不仅生成接口类和_ptr类型,而且添 加了一个_var类。其中的操作与String_var类似。用_ptr给_var进行初始化或赋值,是一个浅赋值。用一个_var对另一个_var进行初始化或赋值,是一个深 赋值。n_var引用与扩展不允许通过其它的_var类型对它们进行隐式的初始化或 扩展赋值。必须显式的调用_duplicate。n同时使用_var和_ptr引用_var引用可以转变为指针引用,因此可以进 行从派生_var类到基_ptr类的扩展赋值。此 赋值是浅赋值。n篏套在用户定义类型中的引用引用篏套在用户定义类型内,就需要使用 _mgr引用。参数传递规则n参数传递规则主要是为了考虑位置透明性和高 效性来制定的。n位置透明性:相同还是不同地址空间,参数的 内存管理规则必须统一。这一条件允许相同的 源代码用于被配置在一起的对象和远程对象。 在此需要用到某些内存管理规则,如变长度的 out参数必须由被调用的函数来分配,并且由调 用程序来释放。n高效性:要尽可能避免参数值的拷贝。通过对 象引用来调用被配置在同一地址空间的CORBA 对象几乎与通过虚拟函数来调用C+对象一样 快。在此要求大的数值应该由引用来传递,而 不是数值。n定长度类型和变长度类型定长度类型:整数类型;浮点数类型;定点数类型;字符 类型;boolean;octet;枚举类型。变长度类型:string和wstring;对象引用;any类型;序列 类型结构、联合和数组是变长还是定长主要是看 他们包含的元素类型。n生成的_out类型out参数往往采用正式的参数类型typename_out。如long 类型的out参数,正式类型为CORBA:Long_out。这是 因为对于定长度类型和变长度类型的out参数,所使用 的内存管理规则不一样。对于定长度类型,生成的_out类型只是引用的类型定义 。例如,Long_out在CORBA名字空间中定义如下:typedef Long 原因在于内存管理规则。变长度类型由被调用的函数进 行内存分配,并且为变长度类型生成的_out类可以确 保内存被正确释放。参数传递规则n简单类型的参数传递简单类型由数值方式还是引用方式来传递 取决于被调用函数是否可以修改参数。in参数采用值传递的方式,它的值不会改 变。inout和out参数采用引用方式传递,因为 在调用过程中可能会修改它的值。 Long_out是Longtypedef Double Darr_slice;virtual Darr_slice* darr_opconst Darr darr_in, Darr_slice * darr_inout, Darr_out darr_out)=0; Darr_slice *表示指向元素类型的指针。参数传递规则nIn参数darr_in使用了正式的参数类型const Darr。根据 C+缺省转换规则,这与把参数类型说明为const CORBA:Double *是一回事, 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:string_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=;char s*;s=p-name();/CORBA:string_free(s);当客户程序调用name方法时,它将调用代理 对象的一个成员函数。事件的顺序如下: (1) 代理的name成员函数创建一个包含操作名 称、对象密钥和操作的in和inout参数(这里 没有)的请求。 (2)代理成员函数把请求写到服务器程序的连 接中,并立即调用连接中阻塞读取的操作( 在此是recv_len)。运行时的客户端程序将阻 塞,直到收到服务器程序的应答为止。(3) 此时,请求将通过网络传输给服务器程序。服务 器程序将阻塞在get_request操作中,等待客户端连 接收到请求。 (4) 客户程序得到外来请求后将继续执行get_request ,通过它来获取操作名与对象密钥。 (5) 运行时的服务器程序调用一个普通的invoke函数 ,其中的一个参数是操作名。Invoke通过操作名 来标识正确的应用程序成员函数,以调用应用程 序代码。变长度参数的内存管理(6) 现在,控制权移交给服务器端的由应用 程序提供的name函数。Name函数通过 string_dup来分配和初始化字符串的内存 ,并且返回指向这个内存缓冲区的指针 。 (7) 控制权又移交给服务器端的运行时ORB ,并且需要运行时ORB传递一个指向已 分配过的字符串的指针。现在,运行时 ORB构造一个包含字符串拷贝的应答, 并且将这个应答发给客户程序。变长度参数的内存管理(8) 服务器端的运行时ORB调用string_free来 释放这个字符串。(因为字符串的内容已 经发送给了客户程序) (9) 现在,服务器端的运行时ORB已经完成 了调度循环中的一次循环,它将再次调 用get_request,直到下一个客户请求到来 后,才能继续下面的操作。 (10) 同时,应答通过网络传递给客户程序 ,客户程序将执行recv_len下面的操作。 返回值是一个字节计数器,用来表示字 符串的长度。(11) 客户端的运行时ORB调用string_alloc来创 建一个包含len字节的缓冲区,并且调用recv ,以便将字符串内容读到缓冲区中。 (12) 返回一个指向包含字符串的缓冲区的指针 后,客户端的存根将结束。 (13) 现在,控制权移交给使用字符串的应用程 序代码,应用程序在最后将通过调用 string_free擦字符串释放掉。变长度参数的内存管理n这里应该注意,客户程序或服务器程序中都没有内存 泄漏现象:(1) 在服务器端,应用程序调用string_alloc,框架中生成 的代码将在把字符串发送给客户程序后,调用 string_free。(2) 在客户端,生成的存根代码将调用string_alloc,并且 向应用程序代码返回一个指向字符串的指针, string_free在应用程序中被调用。变长度参数的内存管理Person_var p=; char * s; s=p-name();string_free
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号