CORBA Programming with TAO - 4.Basic Functions(常用基本方法解析)

跟我从头学TAO编程系列(3) -- 通过实例学习CORBA核心概念 跟我从头学TAO编程系列 编写最简单的TAO应用程序 Stone Jiang 2005119@gmail.com http://www.ace-tao.org   本系列的第一篇我们学会了怎么下载和编译ACE,TAO,第二篇我们编写了最简单的TAO应用程序。这了节,我们通过第二篇的实例来学习CORBA的核心概念。   1.CORBA架构 CORBA的架构如下图: 2 阅读详情
CORBA Programming with TAO - 4.Basic Functions(常用基本方法解析)
摘要:
简要介绍CORBA规范定义的几个常用基本方法的功能及应用中需要注意的问题。
正文:
idl编译器会为每个在idl中声明的interface生成一个对应的代理基类:
class InterfaceName;
以及两个对象引用类型:
InterfaceName_ptr
和
InterfaceName_var
前者是一个指针类型,其定义往往是:
typedef InterfaceName* InterfaceName;
因此,不作过多讨论。
InterfaceName_var则是一个智能指针类,通过使用智能指针类,免去了我们手工维护指针引用计数的工作,大大简化了应用程序的编写。
下面重点对代理基类和_var智能指针类中的几个基本方法进行简单说明。
一、代理基类中定义的几个基本方法
每个代理基类(以及CORBA::Object)都提供如下几个静态方法:
·        _duplicate
返回一个参数指针的拷贝(为了免去对象深拷贝所引起的消耗,实际是通过调整引用计数的方法实现的)
·        _nil
返回相应接口类型的空引用
·        _narrow
尝试将参数指针转型为目标指针,若转换失败,则返回目标类型的空引用。
除了以上静态方法,每个代理类还包括两个方法:
·        _is_a
该方法接收一个类型id信息const char *type_id,并返回一个CORBA::Boolean,用于判断某个引用是否是type_id所指示的类型。
·        _this
该方法返回当前对象的拷贝的引用。
·        _add_ref/_remove_ref
用于增加引用计数和减小引用计数,在我们编写接口实现时可能会用到(客户程序中无法使用这两个方法,因为只有Skeleton代码中会生成这两个方法,客户程序代码也没有必要使用这两个方法来维护引用计数)。
 
此外,在CORBA命名空间中还定义了:
·        CORBA::is_nil
判断某个ptr是否为空
·        CORBA::release
释放参数对象。
而为了比较两个引用是否相同,CORBA::Object中定义了方法:
·        is_equivalent
按照CORBA规范,不使用以上基本方法对CORBA对象或对象指针进行比较、类型转换、非空测试等所产生的行为都是未定义的。
这几个方法本身比较简单,并且后续的文章中将看到上述各基本方法的使用,这里就先不举例了。
二、_var智能指针类中的基本方法
按照CORBA规范,每个_var智能指针类都包括如下几个方法:
·         in
·         out
·         inout
·         _retn
·         ptr
掌握这几个方法的最简单的方法是学习CORBA::String_var类的实现。CORBA::String_var是CORBA::String类的智能指针类,其中封装了一个char*指针。我们来看看TAO是如何实现这几个方法的(见%TAO_ROOT%/tao/CORBA_String.inl):
 
ACE_INLINE const char *
CORBA::String_var::in ( void) const
{
  return this->ptr_;
}
 
ACE_INLINE char *&
CORBA::String_var::inout ( void)
{
  return this->ptr_;
}
 
ACE_INLINE char *&
CORBA::String_var::out ( void)
{
 CORBA::string_free ( this->ptr_);
  this->ptr_ = 0;
  return this->ptr_;
}
 
ACE_INLINE char *
CORBA::String_var::_retn ( void)
{
  char *temp = this->ptr_;
  this->ptr_ = 0;
  return temp;
}
 
/// TAO extension.
ACE_INLINE char *
CORBA::String_var::ptr ( void)
{
  return this->ptr_;
}
 
表面看来似乎没有什么值得注意的,只是返回了几个不同类型的指针:in方法返回一个指针(因仅作为传入参数),inout方法返回一个指针的引用(因不仅要作我传入参数,还要通过函数调用修改其内容),out方法同样返回一个指针的引用(因需要通过函数调用修改其内容),inout方法返回一个指针(因仅作为返回参数,不能修改),ptr也返回一个普通指针,同样也不能修改内容。
但仔细看一看_retn的实现,你会发现,该方法首先保存了指针的内容,然后将指针清0(这样当String_var被释放时就不会free原来的地址空间),最后将该指针返回。也就是说,通过该方法调用,String_var对象所指向的地址空间的控制权被交给了调用该方法的一方,同样,释放地址空间的工作也应该由调用该方法的一方来完成。
而对于out方法,为了保证原指针被安全释放,该方法先释放原来指向的地址空间,并将指针清0,最后返回该指针的引用。因此,被调用的方法内部应负责为该对象分配空间,而释放该空间的工作则是由调用方完成的。
其他对象上述方法的实现与String_var在原理上是基本一致的,只是IDL编译器tao_idl在生成stub和skeleton代码时会分别为定长结构体和变长结构体应用不同的类模板,从而生成不同类型的_var类。对于定长结构体,应用的类模板为TAO_Fixed_Var_T,而对于变长结构体,应用的类模板为TAO_Var_Var_T。二者的区别在于对于定长结构体而言,_retn和out方法与inout方法的实现是一样的,没有清0的过程,以下是TAO_Fixed_Var_T模板类中的相关代码:
 
// Mapping for fixed size.
template< typename T>
ACE_INLINE
T &
TAO_Fixed_Var_T<T>::out ( void)
{
  return *this->ptr_;
}
 
template< typename T>
ACE_INLINE
T
TAO_Fixed_Var_T<T>::_retn ( void)
{
  return *this->ptr_;
}
 
关于_var类的更多信息,可参考%TAO_ROOT%/tao/VarOut_T.inl,或:
三、典型问题解析
上面简单介绍了CORBA编程中常用的几个基本方法,下面在此基础上对内存管理相关的几个问题进行简要分析。
·        包含变长成员变量的结构体的内存释放问题
以下面的idl为例:
 
struct DemoStruct {
      string name_;
};
 
对于如下的代码:
 
int main() {
      //...
      DemoStruct_var demo = new DemoStruct;
      demo.name_ = CORBA::string_dup("Hello");
      //...
}
 
由于我们使用了_var智能指针类,通过new动态分配的空间会在demo对象被销毁时被释放,但是其中通过CORBA::string_dup为成员变量name_所分配的空间是否会泄漏呢?
答案是:不会。这是因为idl文件中结构体的string成员变量经过tao_idl编译后,被映射为TAO_String_Manager,这种类型与String_var基本是一样的,只是String_var不带任何参数的构造函数会将指针ptr_初始化为0,而TAO_String_Manager不带任何参数的构造函数则会将ptr_初始化成一个空字符串,具体可见%TAO_ROOT%/tao/Managed_Types.i及%TAO_ROOT%/tao/CORBA_String.inl。
因此,当结构体被释放时,我们就无需为其中的string的释放问题担心。对于其它包含变长类型的结构体而言,情况是一样的。
·        _var类使用的误区
在使用String_var时有一个问题需要注意,String_var提供了三个构造函数(见%TAO_ROOT%/tao/CORBA_String.h):
 
CORBA::String_var::String_var ( char *p)
 : ptr_ (p)
{
}
 
ACE_INLINE
CORBA::String_var::String_var ( const char *p)
 : ptr_ (CORBA::string_dup (p))
{
}
 
CORBA::String_var::String_var ( const CORBA::String_var& r)
{
  this->ptr_ = CORBA::string_dup (r.ptr_);
}
 
第一个构造函数仅对指针p进行浅拷贝,保存到内部的ptr_中,而后面两个则通过深拷贝来构造String_var对象。
两种不同的构造方式区别虽然比较小,但可能引起一些十分隐蔽的问题。如下面的代码就存在问题:
 
String_var str( "Hello");
 
因为上述代码会使用第一个而不是第二个构造函数来构造str,从而使得str获得静态地址空间"Hello"的控制权,并在str被析构时尝试释放该空间,这显然是错误的。要避免该错误,我们应该总是强制使用第二个构造函数,或在构造Stirng_var对象前主动复制String的内容,如:
 
String_var str1(( const char*)"Hello");
String_var str2(CORBA::string_dup( "Hello"));
 
除非你清楚地知道第一个构造函数是你需要的。
对于其它_var类型而言,不存在与上面第二种构造方式等价的构造函数,我们总是使用第一种形式的构造函数,即新构造的_var对象会获得指针的控制权。
与上面第三种构造方式类似,如果你传入的是一个_var引用,则使用的是如下的构造函数:
 
template< typename T>
TAO_Var_Base_T<T>::TAO_Var_Base_T ( const TAO_Var_Base_T<T> & p)
 : ptr_ (p.ptr_ ? new T (*p.ptr_) : 0)
{
}
 
该构造函数会对传入的_var引用进行深拷贝。
·        对远程方法调用内存管理问题的解释
CORBA内存分配/释放的原则很简单:各自负责自己分配空间的释放,C/S两端内存的分配与释放(以及更新)不会自动通知另一方。
对于Client代码而言,由Client代码负责释放的空间还包括ORB在unmarshalling期间创建的Server的指针的镜像,即Server端指针的本地拷贝,这些空间可能是out/inout参数或者作为接口方法的返回值通过方法调用获得的。
这在理解上应该没有什么问题。但是,其中对于Server方的内存管理,我们没有考虑。以如下代码为例:
 
DemoStruct* DemoIntf::foo() {
      DemoStruct_var var = new DemoStruct;
      //...
      return var._retn();
}
 
当函数返回时,Client方ORB会通过unmarshalling创建一个该指针所指内存区域的镜像,然后访问该指针,最后由Client方负责该区域的释放;但是我们说过,C/S双方分配和释放内存并不会自动通知另一方,对于Server方而言,由于_retn方法会释放原_var对象对其ptr_指针所指地址空间的控制权,原来由_var对象所管理的空间似乎变得失去了控制,那么这一部分内存是否会泄漏呢?
同样,答案是不会,这是因为ORB在将该指针进行marshalling并传递给Client后,会负责指针所指空间的释放,同样对于in、out、inout参数的管理也是类似的。
 
结合上面对Server方内存管理方式的讨论,我们来看看下面的例子。
对于如下的idl文件:
 
struct DemoStruct {
      string name_;
};
 
interface DemoIntf {
      DemoStruct get();
};
 
有类似下面的实现:
 
class DemoIntf : ...
{
private:
      DemoStruct_var demo_;
public:
      DemoStruct* get() {
            return demo_;
      }
};
 
上述实现初看起来可以正常工作,但是根据上面的讨论,ORB会释放返回值指针的地址空间,这将导致demo_被意外释放,最终导致错误的发生。因此,我们应该将实现代码改为:
 
DemoStruct* get() {
      ::Device::DeviceID_var dev_id = new ::Device::DeviceID;
      dev_id->device_name = CORBA::string_dup(id_->device_name);
      return dev_id._retn();
}
 
而客户方代码的代码是这样的:
 
::Device::DeviceID_var device_id = this->device_id();
参考:
1.      Michi Henning, Steve Vinoski. Advanced CORBA Programming with C++. Addison-Wesley, 1999.
2.      Douglas C. Schmidt & Bala Natarajan. CORBA Tutorial. http://www.cs.wustl.edu/~schmidt/PDF/corba4.pdf
 
U2000北向 CORBA客户端代码Java编程示例 ** 客户端代码Java编程示例 **  使用生成u2000_idl.jar和C:\JacORB-2.2.4\lib内的jar包进行客户端代码的开发 图 Eclipse 代码demo环境 通过下面编程示例demo(包含4个类Client,AlarmReciever,TANmsSession_IImpl,Util),实现获取EmsSession、查询U2000支持的manager列表和事件通知订... 阅读详情

相关推荐

嵌入式SPI总线抽象设计:跨平台驱动与分层解耦实践

SPI(串行外设接口)是嵌入式系统中应用最广泛的同步串行通信协议,其核心价值在于高吞吐、低开销与硬件简洁性。其工作原理基于主从架构、全双工/半双工时序及片选(CS)控制,依赖CPOL/CPHA组合定义四种标准模式。在工程实践中,SPI常面临硬件资源受限、多外设共用总线、MCU平台迁移等挑战,导致驱动复用率低、维护成本高。通过结构体+函数指针实现的分层抽象——将物理总线、协议适配与设备驱动解耦,可显著提升代码可移植性与扩展性。该方法天然支持硬件SPI与GPIO模拟SPI双模式切换,并已在STM32等主流MCU

weixin_42601134的博客 60

Object的浅拷贝与深拷贝

JavaScript对象的浅拷贝和深拷贝的实现与区别

ITjun666的博客 1077

Halcon 算子 select_shape

作用:借助形状特征选择区域; 参数翻译(对应以上参数顺序): 输入区域、 输出满足条件的区域、 输入参数形状特征('anisometry', 'area', 'area_holes', 'bulkiness'等)、 输入参数关系符('and', 'or')、 输入参数下限值(0.0 ≤ Min ≤ 99999.0)、 输入参数上限值(Max >= Min 并且0.0 ≤ Max ≤ 99999.0); 描述: 算子select_shape根据形状特征选择区域,对于...

奔跑的郑的博客 2万+

为什么不建议对Object进行强转?吾认为有如下几点!

如果只是自己用,强转不强转都无所谓。但是大型商业公司里,必定需要和上下游打交道。Object视角下,别人无法得到任何有价值的信息。再简单的ToString()后,将会面临,无法序列化的问题。故建议少用强转。

山鬼谣的专栏 509

PX4飞控与MAVROS实战:从零搭建无人机ROS通信环境(附常见报错解决)

本文详细介绍了如何从零搭建PX4飞控与ROS的通信环境,重点解析了MAVROS的安装、硬件连接、串口权限配置以及坐标系转换等核心步骤。针对GeographicLib数据下载失败、串口权限不足等常见报错提供了实用解决方案,并附有Offboard模式控制的代码示例,帮助开发者快速建立稳定的无人机ROS开发环境。

dapp9builder的博客 335

仿真学习系列(四十三):Sigrity仿真之平面谐振分析

在 SIGRITY 中,平面谐振分析(Plane Resonance Analysis)是一种用于分析信号完整性(SI)问题的高级仿真方法,尤其关注于层间电磁波的传播、谐振现象和信号衰减等问题。平面谐振分析通常用于电源分配网络(PDN)、信号线和参考平面之间的相互作用。本文将详细介绍如何在 SIGRITY 中进行平面谐振分析,并提供一些实用的分析方法与步骤,帮助工程师们识别和优化可能存在的设计问题。

案例文章,高速信号 478

CORBA技术系列二:CORBA基础概念-对象引用

系列二 对象引用         CORBA作为传统中间件的典型代表,强调屏蔽底层网络对上层应用的差异性来建立一个统一的位置视图,使得程序员可以使用经典的面向对象思想开发客户程序和服务程序,而不受底层网络具体通信协议的困扰。举例而说,假如程序员开发了两个对象A和B,A位于机器Host1上,而B位于机器Host2上,业务逻辑要求A调用B的方法method()。在传统的TCP/IP Socket编程中

软件技术的虔诚学子 2649

PCL 计算点云包围球【2025最新版】

包围球通常用于简单排斥,因为与球体相交的方程很简单,同样重要的是,旋转一个球体并不会改变其范围。因此,当包围球用于简单排斥时,如果球体中心是对象的原点,则可以忽略对象的方向。

点云侠的博客 2068

CORBA Programming with TAO - 4.Basic Functions(常用基本方法解析)

CORBA Programming with TAO - 4.Basic Functions(常用基本方法解析)摘要:简要介绍CORBA规范定义的几个常用基本方法的功能及应用中需要注意的问题。正文:idl编译器会为每个在idl中声明的interface生成一个对应的代理基类:class InterfaceName;以及两个对象引用类型:InterfaceName_ptr

大卫的思维空间 4445

YOLO26涨点改进 | 小目标损失函数独家改进篇 | TGRS 2025 | 引入AdaFocalLoss损失函数,改进小目标检测,自适应聚焦小目标与样本分布不平衡,提升检测精度与训练稳定性

目录一、前言:YOLO26原生损失函数在小目标检测中的核心痛点(涨点瓶颈)1.1 小目标权重不足,聚焦能力薄弱1.2 样本分布不平衡适配性差,正负样本权重失衡1.3 训练不稳定,易出现梯度消失/震荡1.4 未区分小目标与背景的冗余干扰,误检率高二、TGRS 2025顶刊灵感解析:自适应聚焦损失的核心逻辑三、全网独家创新:AdaFocalLoss损失函数设计与YOLO26适配(核心重点,可复现)3.1 AdaFocalLoss函数整体设计(独家设计,清晰可复现)3.2 各核心模块详细设计(独家创新,可直接复现

qq_36130719的博客 202

Altium Designer应用技巧5: Altium Live账号的获得

为了更好的应用Altium Designer,我们需要得到一个Altium Live账号,但从其英文或者中文官方网站取得,都需要7个工作日的时间,而且对于个人用户来说,并不是100%都能够获取到。本文介绍一种,从俄罗斯Altium官方网站获取账号的方法,可以立即使用。     1、点击http://live.altium-ru.com/#Join网址进入俄罗斯Altium官方网站,Altiu

snmplink的博客 1万+

CORBA prototype of _duplicate, _narrow, object_to_string, string_to_object

example_ptr _duplicate(example_ptr _obj);        // example, IpInterface_ptr _duplicate (IpInterface_ptr obj);    您的客户端程序调用 _duplicate 成员函数时,对象引用的引用数递增一个并返回    同一对象引用。您的客户端程序可以使用 _duplicate() 成员函数增加

程序员码工的专栏 1924

数据库系统概论第五版课后习题答案第十二章

对元组的插入、删除、修改;语义检查的具体做法是,DBMS读取数据字典,检查是否存在与该语句中的表、视图或索引等要创建的对象相同的对象名,检查该用户是否具有创建数据库对象的权限。答:操作系统提供的封锁机制和DBMS的封锁机制在封锁对象、封锁对象的状态、封锁的粒度、及封锁的类型上存在很大的差别,操作系统的封锁机制不能直接应用在DBMS中,DBMS必须重新设计,来满足复杂的封锁需求。数据库的建立和维护包括数据库的初始建立、数据的转换、数据库的转储和恢复、数据库的重组织和重构造以及性能监测分析等功能。

wenling54321的博客 693

CORBA基本概念、函数

摘要: 简要介绍CORBA规范定义的几个常用基本方法的功能及应用中需要注意的问题。 正文: idl编译器会为每个在idl中声明的interface生成一个对应的代理基类: class InterfaceName; 以及两个对象引用类型: InterfaceName_ptr 和 InterfaceName_var 前者是一个指针类型,其定义往往是

u012719556的专栏 4183

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

CORBA Programming with TAO - 5.Hello World(简单实例)

CORBA Programming with TAO - 5.Hello World(简单实例) 摘要: 前面对CORBA编程的基础知识进行了简单介绍,本篇中,我们将实例讲解如何利用TAO中进行CORBA编程。 一、编写IDL 1、建一个空的Solution,然后在该Solution目录下新建一个名为idl的Win32 Static Library工程(对于一般的TAO工程,无需单独为...

pleasetojava 215

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

上一篇: CORBA Programming with TAO - 2.Compile Source Code(编译ACE/TAO/CIAO)
下一篇: CORBA Programming with TAO - 5.Hello World(简单实例)
Stone
博客等级 码龄21年 1715粉丝 158原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值