CORBA Programming with TAO - 3.IDL Data Type(数据类型与Mapping)

 转自:http://blog.vckbase.com/billdavid/archive/2006/05/12/20027.html

摘要:
简要介绍TAO支持的IDL数据类型及其C++ Mapping关系。
一、简单基本数据类型(Simple Basic Types)
TAO支持以下简单基本数据类型( %TAO_ROOT%/tao/Basic_Types.h ):
IDL
C++
boolean
CORBA::Boolean
char
CORBA::Char
octet
CORBA::Octet
short
CORBA::Short
unsigned short
CORBA::UShort
long
CORBA::Long
unsigned long
CORBA::ULong
long long
CORBA::LongLong
unsigned long long
CORBA::ULongLong
wchar
CORBA::WChar
float
CORBA::Float
double
CORBA::Double
long double
CORBA::LongDouble
以上各简单基本类型对应的C++类型只是对应平台上基本类型的typedef(Java虚拟机之所以能够在各平台上保证统一的数据长度,其实现原理也是如此),但在编写应用程序时,为了保证程序的可移植性,应该总是使用CORBA命名空间中的类型标识。此外,需要注意:在上面的所有类型中,没有我们熟悉的C++基本类型byte(被Octet取代)、int(被Long取代)。
二、复杂基本数据类型(Complex Basic Types)
除以上简单基本数据类型外,TAO还支持以下复杂基本数据类型:
IDL
C++
string
CORBA::TAO_String_Manager(%TAO_ROOT%/tao/Managed_Types.h)
wstring
CORBA::TAO_WString_Manager(%TAO_ROOT%/tao/Managed_Types.h)
any
CORBA::Any(%TAO_ROOT%/tao/AnyTypeCode/Any.h)
其中两种String类型在使用时需要注意:
1、应该总是使用TAO提供的(也是CORBA规范规定的)如下字符串操作函数:
 
char * string_alloc(ULong len);
char * string_dup(const char *);
void string_free(char *);
WChar * wstring_alloc(ULong len);
WChar * wstring_dup(const WChar *);
void wstring_free(WChar *);
来进行字符串操作,以提高系统的可移植性。
2、(w)string_alloc/(w)string_dup后必须调用(w)string_free来释放分配的资源,为了避免忘记(w)string_free带来的麻烦,有些情况下,我们可以考虑使用String_var类型(String_var是String类对应的智能指针类,除了TAO本身支持的智能指针类型外,tao_idl在生成代码时会自动为每个Object添加一个对应的var类型)。
3、(w)string_alloc(n)会分配n+1个字符(不是字节)空间。
以下是一个简单的字符串操作的例子:
 
#include <tao/corba.h>  
#include <iostream>
using namespace std;
 
int main(int argc, char **argv) {
      char * p = CORBA::string_alloc(5); // Allocates 6 bytes
      strcpy(p, "Hello"); // OK, "Hello" fits  
      cout << p << endl;  
      CORBA::string_free(p);  
      CORBA::String_var s = CORBA::string_dup("World");
      cout << s.in() << endl;
       return 0;
}
注:如果你在编译该程序时遇到困难,请在阅读完本系列的第五篇文章后再来测试该程序(下同)。
 
CORBA::Any与Windows开发中常用的VARIANT类型相当,可以在其中存入任意其他类型的数据,但Any更具有面向对象的风格。在Windows应用中向VARIANT写入信息时需要先设置写入的数据类型,而从中读出数据时往往需要用switch进行判断,相比之下Any的使用就简单多了,我们可以通过<=操作符来向Any类型变量写入信息,而通过>=操作符从Any变量中读出信息。与从VARIANT中解析数据不同的是,由于重载的>=操作符返回的是一个表示转换成功或者失败的标志,因此,我们总是使用if...else而不是switch来对解析结果进行判断。下面是一个使用Any的例子:
 
#include <tao/AnyTypeCode/Any.h>  
#include <iostream>
using namespace std;
 
int main(int argc, char **argv) {
      CORBA::Any a;
      CORBA::Octet o;
      CORBA::Long l;
 
      a <<= CORBA::Long(1); // a contains 1 with CORBA::Long type
      if (a >>= l) {
            cout << "Long: " << l << endl;
      } else {
            cout << "Unknown value." << endl;
      }
 
      a <<= CORBA::Any::from_octet(65); // a contains 64 with CORBA::Octet type
 
      if (a >>= CORBA::Any::to_octet(o)) {
            cout << "Octet: " << o << endl;
      } else {
            cout << "Unknown value." << endl;
      }  
      return 0;
}
注:过度使用 Any 类型将对程序的处理性能造成影响。
 
此外,CORBA规范还规定了一种不太常用的数据类型:CORBA::Fixed,它是一种特殊的浮点类型,在构造fixed类型变量时必须指定两个参数:总位数(不含小数点)与精度,而CORBA::Fixed则提供了多种从其它基本类型构造Fixed类型的方法,你甚至可以从字符串类型构造一个Fixed类型变量。但是,目前TAO尚不支持Fixed类型。
三、构造类型(Constructed Types)
除了上面的基本类型外,我们还可以在idl中使用struct、sequence、union、array等几种构造类型:
·        struct
struct与C语言中的struct基本上是等价的,其中只能包含变量定义,不能定义方法,对定义的变量进行初始化,或定义union型变量。
·        sequence
sequence与STL中的vector比较类似,可以用它来存储相同类型的变量,并且可以“自由”扩充,因此,sequence往往可以在传递“变长”参数时发挥重要作用。经过idl处理,sequence会被映射成相应的类。下面举一个sequence的例子:
1、首先,定义如下的idl文件:
typedef sequence<string> StrSeq;
将其存为strseq.idl,并在控制台下对其进行编译,命令如下:
tao_idl -Sc strseq.idl
编译后,我们将得到一个名为strseq.h的头文件;
2、新建一控制台工程,并在主文件中添加如下代码(注:此例全部代码取自<Advanced CORBA Programming with C++>):
 
#include "strseqC.h"  
#include <iostream>
using namespace std;
 
int main(int argc, char **argv) {
      const char * values[] = { "first", "second", "third", "fourth" };
      StrSeq myseq; // Create empty sequence
      // Create four empty strings
      myseq.length(4);
      for (CORBA::ULong i = 0; i < myseq.length(); i++)
            myseq[i] = values[i]; // Deep copy
      // Print current contents
      for (CORBA::ULong j = 0; j < myseq.length(); j++)
            cout << "myseq[" << j << "] = /"" << myseq[j].in() << "/"" << endl;
      cout << endl;
      // Change second element (deallocates "second")
      myseq[1] = CORBA::string_dup("second element");
      // Truncate to three elements
      myseq.length(3); // Deallocates "fourth"
      // Grow to five elements (add two empty strings)
      myseq.length(5);
      // Initialize appended elements
      myseq[3] = CORBA::string_dup("4th");
      myseq[4] = CORBA::string_dup("5th");
      // Print contents once more
      for (CORBA::ULong k = 0; k < myseq.length(); k++)
            cout << "myseq[" << k << "] = /"" << myseq[k].in() << "/"" << endl;  
      return 0;
}
·        union
idl中的union类型与C++中的union不是等价的,它实际上被映射成了对应的class,同时在使用上与C++中的union也有极大区别。以下面的idl为例:
 
union U switch (char) {
      case 'L':
            long long_mem;
      case 'c':
      case 'C':
            char char_mem;
      default:
            short short_mem;
};
 
其意义可以解释为:
类型U可以用于存放三种类型的值:Long型、Char型、Short型,你可以分别用long_mem、char_mem、short_mem取出这些值。当使用一个Long型变量初始化该union变量时,类型标志为L(或者反过来,当类型标志为L时,可以在其中存放一个Long型的值);当用一个Char型变量初始化该union变量时,类型标志为c或者C;当用一个Short型初始化该union变量时,类型标志为其它值。
但是,在使用union类型时需要特别注意:不要尝试将类型标志设置为一种类型(通过_d方法),而用另一种类型去初始化它;或者,反过来,用一种类型去初始化它,然后又尝试将类型标志修改为其它值。
下面是一个使用上述idl定义的例子:
 
#include <iostream>
using namespace std;  
#include <assert.h>
 
int main(int argc, char **argv) {
      U my_u; // 'my_u' is not initialized
      // my_u._d('c');
      my_u.long_mem(99); // Activate long_mem
      assert(my_u._d() == 'L'); // Verify discriminator
      assert(my_u.long_mem() == 99); // Verify value
      // my_u._d('c');
      cout << my_u.char_mem() << endl;
}
注:请自行添加相关头文件。
 
当union中还包括其他变长类型时,情况将变得很复杂,但使用上并没有太大差异,这里就不深入讨论了,感兴趣的朋友可以阅读参考1的相关章节。
·        array
array并不是一个idl所使用的关键字,它表示的是普通定长数组,它被映射成C++代码时也是一个普通的定长数组,因此,其用法比较简单。下面是一个使用array的idl的例子:
 
typedef float FloatArray[4];
 
typedef string StrArray[15][10];
struct S {
      string s_mem;
      long l_mem;
};
 
typedef S StructArray[20];
 
相关测试代码如下:
 
#include <iostream>
using namespace std;
 
int main(int argc, char **argv) {
      FloatArray my_f = { 1.0, 2.0, 3.0 };
      my_f[3] = my_f[2];
      StrArray my_str;
      my_str[0][0] = CORBA::string_dup("Hello"); // Transfers ownership
      my_str[0][1] = my_str[0][0]; // Deep copy
      StructArray my_s;
      my_s[0].s_mem = CORBA::string_dup("World"); // Transfers ownership
      my_s[0].l_mem = 5;
}
注:请自行添加相关头文件。
参考:
1.      Michi Henning, Steve Vinoski. Advanced CORBA Programming with C++. Addison-Wesley, 1999.
2.      OMG. C++ Language Mapping, v1.1. http://www.omg.org/cgi-bin/apps/doc?formal/03-06-03.pdf
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值