(1)IDLマッピング
IDL言語で共用体unionを指定した場合、C++言語ではデータ型を識別する弁別情報_dと共用体データ域_ptrから構成される共用体クラスにマッピングされます。
以降では、以下のIDL定義例をもとに説明します。
module ODsample{
union samplefix switch(long){ // 共用体(固定長)
case 1: long para1;
case 2: long para2;
};
union samplevar switch(long){ // 共用体(可変長)
case 1: long para1;
case 2: string para2;
};
interface uniontest{
samplefix op2(
in samplefix uni1,
out samplefix uni2,
inout samplefix uni3
);
samplevar op1(
in samplevar uni1,
out samplevar uni2,
inout samplevar uni3
);
};
}; class samplefix
{
public:
samplefix(); // デフォルトコンストラクタ
samplefix( const samplefix& ); // コピーコンストラクタ
~samplefix(); // デストラクタ
samplefix &operator=( const samplefix & ); // 代入演算子
void _d( CORBA::Long ); // 弁別子情報の設定
CORBA::Long _d() const; // 弁別子情報の取得
void para1( CORBA::Long ); // para1データの設定
CORBA::Long para1() const; // para1データの取得
void para2( CORBA::Long ); // para2データの設定
CORBA::Long para2() const; // para2データの取得
private:
CORBA::Long __d; // 弁別情報
void *_ptr; // データ域
};
class samplevar
{
public:
samplevar(); // デフォルトコンストラクタ
samplevar( const samplevar& ); // コピーコンストラクタ
~samplevar(); // デストラクタ
samplevar &operator=( const samplevar & );
// 代入演算子
// 弁別子アクセス関数
void _d( CORBA::Long ); // 弁別子情報の設定
CORBA::Long _d() const; // 弁別子情報の取得
// メンバアクセス関数
void para1( CORBA::Long ); // para1データの設定
CORBA::Long para1() const; // para1データの取得
void para2( CORBA::Char* ); // para2データの設定
void para2( const CORBA::Char* ); // para2データの設定
void para2( const CORBA::String_var& );
// para2データの設定
CORBA::Char * para2() const; // para2データの取得
private:
CORBA::Long __d; // 弁別情報
void *_ptr; // データ格納域
};(2)クライアントアプリケーションで扱うパラメタ(固定長)
共用体(固定長)のパラメタ(in、out、inout)を扱う場合、宣言した共用体変数をパラメタに指定します。領域の獲得/解放を行う必要はありません。データ型識別情報、データ値をメンバ関数を使って設定します。
以下にクライアントアプリケーションでの処理例を示します。
ODsample::uniontest_ptr obj;
ODsample::samplefix unif0, unif1, unif2, unif3;
CORBA::Environment env;
unif1.para2(100); // inパラメタの設定
unif3.para1(200); // inoutパラメタの設定
// サーバ呼出し
unif0 = obj->op2( unif1, unif2, unif3, env );(3)クライアントアプリケーションで扱うパラメタ(可変長)
クライアントアプリケーションのパラメタの扱いについて、以下に示します。
パラメタ | サーバへ渡すパラメタ | サーバから渡されたパラメタ |
|---|---|---|
in | 可変長データ域を動的に獲得する場合は、newを使用します。 | - |
inout | (inパラメタと同じ) | 領域はスタブで自動的に獲得されます。 |
out | - | (inoutパラメタと同じ) |
クライアントおよびスタブで動的に獲得した領域は、不要になった時点でdelete(C++演算子)で解放する必要があります。deleteを発行すると、構造体の可変長データの領域も解放されます。
以下にクライアントアプリケーションでの処理例を示します。
ODsample::uniontest_ptr obj;
ODsample::samplevar *uni0, uni1, *uni2, uni3;
CORBA::Environment env;
uni1.para1(10); // inパラメタ設定
uni3.para2( (const CORBA::Char *)"INOUT::para2" );
// inoutパラメタ設定
// サーバ呼出し
uni0 = obj->op1( uni1, uni2, uni3, env );
// 領域解放
CORBA_free( uni0 ); // 復帰パラメタ
CORBA_free( uni2 ); // outパラメタ(4)サーバアプリケーションで扱うパラメタ(固定長)
共用体(固定長)のout、inoutパラメタを扱う場合、データ型の識別情報とデータの値をメンバ関数を使って共用体クラスのインスタンスに設定します。共用体の領域の獲得/解放を行う必要はありません。
ODsample::samplefix
ODsample_uniontest_impl::op2(
const ODsample::samplefix &uni1,
ODsample::samplefix &uni2,
ODsample::samplefix &uni3,
CORBA::Environment &env
)
throw( CORBA::Exception )
{
// outパラメタの処理
uni2.para1(10); // データの値の設定
// inoutパラメタの処理
uni3.para2(100); // データの値の設定
// 復帰値の処理
ODsample::samplefix uni;
uni.para1(100); // データの値の設定
return( uni );
}(5)サーバアプリケーションで扱うパラメタ(可変長)
サーバアプリケーションのパラメタの扱いについて、以下に示します。
パラメタ | クライアントからのパラメタ領域 | クライアントへのパラメタ領域 |
|---|---|---|
in | スケルトンで自動的に獲得/解放されます。 | - |
inout | スケルトンで自動的に獲得されます。 | メンバアクセス関数で新しいデータを設定します(古い領域は自動的に解放されます)。 |
out | - | new/データ域獲得関数で共用体領域/可変長データ域を獲得します。 |
以下にサーバアプリケーションでの処理例を示します。
ODsample_samplevar *
ODsample_uniontest_impl::op1(
const ODsample::samplevar &uni1,
ODsample::samplevar *&uni2,
ODsample::samplevar &uni3,
CORBA::Environment &env )
{
// outパラメタ
uni2 = new ODsample::samplevar; // 領域獲得
uni2->para2( (const CORBA::Char *)"OUT::param" ); // パラメタ設定
// inoutパラメタ
uni3.para1(10); // パラメタ設定
// 復帰パラメタ
ODsample::samplevar *uni = ODsample::samplevar; // 領域獲得
uni.para1(30); // パラメタ設定
return( uni );
}(6)共用体クラスのメソッド
共用体クラスで定義されているメソッドと意味を以下に示します。
シーケンスクラスのメンバ | 意味 |
|---|---|
デフォルトコンストラクタ | インスタンス生成時、データ格納域_ptrを0で初期化します。 |
コピーコンストラクタ | インスタンス生成時、_ptrの領域を獲得し、パラメタで指定された値を_ptr、__dに設定します。メモリ不足により領域の獲得に失敗した場合、_ptrがNULLに設定され、__dが0に設定されます。 |
デストラクタ | インスタンス破壊時、_ptr、_dの値に対する領域を解放します。 |
代入演算子 | _ptrの領域を獲得し、パラメタで指定された値を_ptr、_dに設定します。メモリ不足により領域の獲得に失敗した場合、_ptrがNULLに設定され、__dが0に設定されます。 |
弁別子アクセス関数 | _d(Long)関数はパラメタで指定した値を弁別子に設定します。 |
メンバアクセス関数 | “メンバ名(変数)”の形式で呼び出すことによりメンバの値をデータ格納域に設定します。メモリ不足によりデータ格納域の獲得に失敗した場合、_ptrがNULLに設定され、__dが0に設定されます。 |
デフォルトコンストラクタは、データ格納域_ptrを0に初期化します。デフォルトコンストラクタの使用例と処理内容を以下に示します。
// IDL
union UnionSmp switch(long){
case 1: long para1;
case 2: string para2;
};
// 使用例
UnionSmp *uni1 = new UnionSmp();
// 以下のデフォルトコンストラクタUnionSmp()が呼ばれ、uni1 が初期化されます。
UnionSmp uni2;
// 以下のデフォルトコンストラクタUnionSmp()が呼ばれ、uni2 が初期化されます。
// デフォルトコンストラクタ
UnionSmp::UnionSmp()
{
_ptr = (void *)0;
} コピーコンストラクタは、パラメタで指定された共用体のデータ__d(弁別情報)、_ptr(データ格納域)のデータを複写します。この際、_ptrの領域が獲得されます。メモリ不足により領域の獲得に失敗した場合、_ptrがNULLに設定され、__dが0に設定されます。
コピーコンストラクタの使用例と処理内容を以下に示します。
// IDL
union UnionSmp switch(long){
case 1: long para1;
case 2: string para2;
};
// 使用例
UnionSmp *uni1 = new UnionSmp();
uni1->para1(10); // メンバアクセス関数
UnionSmp uni2 = new UnionSmp(*uni1);
// コピーコンストラクタにより、__dに1、_ptrに値10が設定されます
if ( uni2._d() == 0 ) { // 成否判定(__dが0の場合、失敗)
... // 失敗している場合、エラー処理
}
// コピーコンストラクタ
UnionSample::UnionSmp(const UnionSmp &_UnionSmp )
{
switch( _UnionSmp.__d ) {
case 1:
para1( _UnionSmp.para1() );
break;
case 2:
para2( (const CORBA::Char *)_UnionSmp.para2);
break;
}
__d = _UnionSmp._d();
} デストラクタは、_ptrの領域を解放します。デストラクタの使用例を以下に示します。
// IDL
union UnionSmp switch(long){
case 1: long para1;
case 2: string para2;
};
// 使用例
UnionSmp *uni1 = new UnionSmp();
CORBA::Char *str = CORBA::string_alloc(5);
strcpy( str, "data");
uni1->para2(str); // 共用体メンバ関数。strのポインタが_ptrに渡されます
delete uni1; // デストラクタが呼ばれ_ptr(str)の領域も解放されます。 // IDL
union UnionSmp switch(long){
case 1: long para1;
case 2: string para2;
};
// 使用例
UnionSmp *uni1 = new UnionSmp();
uni1->para1(10); // メンバアクセス関数
UnionSmp uni2 = *uni1;
// 代入演算子により、uni2の_dに1、_ptrに値10が設定されます。
if ( uni2._d() == 0 ) { // 成否判定(__dが0の場合、失敗)
... // 失敗している場合、エラー処理
}
// 代入演算子
パラメタで指定された値を_ptr,_dに設定します。
UnionSmp&
UnionSmp::operator=( const UnionSmp &_UnionSmp )
{
if( _ptr ){
switch( __d ){
case 1 :
{
delete _ptr;
_ptr = 0;
}
break;
case 2 :
{
CORBA::String_var *_tmp = ( CORBA::String_var* )_ptr;
delete _tmp;
_ptr = 0;
}
}
}
switch( _UnionSmp.__d ){
case 1:
para1( _UnionSmp.para1() );
case 2:
para2( (const CORBA::Char *)_UnionSmp.para2() );
break;
}
__d = _UnionSmp._d();
return *this;
} 弁別子アクセス関数は、弁別情報(__d)への設定および弁別情報獲得のためのメンバ関数です。弁別子アクセス関数の使用例と処理内容を以下に示します。
// IDL
union UnionSmp switch(long){
case 1: long para1;
case 2: string para2;
};
// 使用例
UnionSmp *uni1 = new UnionSmp();
uni1->para1(10);
CORBA::Long l = uni1->_d(); // lの値は1
uni1->_d(2); // __dに2が設定されます。
l = uni1->_d(); // lの値は2メンバアクセス関数は、メンバ設定関数とメンバ取得関数が提供されます(関数名はメンバ名と同じ)。メンバアクセス関数の使用例と処理内容を以下に示します。
// IDL
typedef long Bytes[64];
struct S {
long len;
};
union UnionSmp switch(long){
case 1: long x;
case 2: Bytes y;
case 3: string z;
case 4: S w;
};
// 使用例
UnionSmp *uni1 = new UnionSmp();
uni1->x(10); // メンバ設定関数。__dに1、_ptrに値10が設定されます。
if ( uni1->_d() == 0 ) { // 成否判定(__dが0の場合、失敗)
... // 失敗している場合、エラー処理
}
UnionSmp *uni2 = new UnionSmp();
Bytes data;
for ( int i = 0; i < 64; i++ )
data[i] = i;
uni2->y(data); // __dに2、_ptrにdataを複写します。
if ( uni2->_d() == 0 ) { // 成否判定(__dが0の場合、失敗)
... // 失敗している場合、エラー処理
}
UnionSmp uni3(*uni2);
Bytes_slice *slice = uni3->y(); // _ptrに設定されているポインタを返します。
UnionSmp uni4;
CORBA::Char *str = CORBA::string_alloc(4);
strcpy( str, "ZZZ" );
uni4.z( str ); // __dに3、_ptrにstrのポインタを設定します。
uni4.z( (const CORBA::Char *)"XXX" );
// _ptrに設定されている領域を解放し、データ”XXX”を複写します
// (const付き:データの複写,なし:ポインタ渡し)
if ( uni4._d() == 0 ) { // 成否判定(__dが0の場合、失敗)
... // 失敗している場合、エラー処理
}
UnionSmp uni5;
S str_data;
str_data.len = 5;
uni5.w( data_len ); // __dに4、_ptrにdata_lenを複写します。
if ( uni5._d() == 0 ) { // 成否判定(__dが0の場合、失敗)
... // 失敗している場合、エラー処理
}
S str_data2;
str_data2 = uni5.w(); // str_data2に_ptrに設定されているデータが複写されます。