(1)IDLマッピング
IDL言語でany型を指定した場合、C++言語では、データ型を識別するTypeCode(_tc)、データ域のアドレス(_value)、リリースフラグ(_release)をprivateデータに持つCORBA::Anyクラスにマッピングされます。CORBA::Anyクラスのインスタンスはnew(C++の演算子)で生成します。privateデータのアクセスはCORBA::Anyクラスのメソッドを用います。インスタンス生成の記述形式を以下に示します。
CORBA::Any *data = new CORBA::Any(
CORBA::TypeCode_ptr _tc, // データ型識別TypeCode
void *_value, // データ域アドレス
CORBA::Boolean release ); // リリースフラグ class CORBA {
class Any {
public:
Any(); // デフォルトコンストラクタ
Any( const Any & ); // コピーコンストラクタ
Any( TypeCode_ptr tc, void *value,
Boolean release = CORBA_FALSE );
// コンストラクタ(型定義されていない値用)
~Any(); // デストラクタ
Any &operator=( const Any & ); // 代入演算子
// 左シフト代入演算子
void operator<<=( Short ); // Short型
void operator<<=( UShort ); // UShort型
void operator<<=( Long ); // Long型
void operator<<=( ULong ); // ULong型
void operator<<=( LongLong ); // LongLong型
void operator<<=( Float ); // Float型
void operator<<=( Double ); // Double型
void operator<<=( LongDouble ); // LongDouble型 (Windows(R)、Solaris のみ)
void operator<<=( const Any & ); // Any型
void operator<<=( const Char * ); // Char * (String) 型
void operator<<=( const WChar * ); // WChar * (WString) 型
// 右シフト代入演算子
Boolean operator>>=( Short & ) const; // Short型
Boolean operator>>=( UShort & ) const; // UShort型
Boolean operator>>=( Long & ) const; // Long型
Boolean operator>>=( ULong & ) const; // ULong型
Boolean operator>>=( LongLong & ) const; // LongLong型
Boolean operator>>=( Float & ) const; // Float型
Boolean operator>>=( Double & ) const; // Double型
Boolean operator>>=( LongDouble & ) const; // LongDouble型 (Windows(R)、Solaris のみ)
Boolean operator>>=( Any & ) const; // Any型
Boolean operator>>=( Char *& ) const; // Char * (String) 型
Boolean operator>>=( WChar *& ) const; // WChar * (WString) 型 // boolean, octet, char の設定に必要な特別な helper 型
struct from_boolean {
from_boolean( Boolean b ) : val(b) {}
Boolean val;
};
struct from_octet {
from_octet( Octet o ) : val(o) {}
Octet val;
};
struct from_char {
from_char( Char c ) : val(c) {}
Char val;
};
void operator<<=( from_boolean );
void operator<<=( from_octet );
void operator<<=( from_char );
// boolean, octet, char の抽出に必要な特別な helper 型
struct to_boolean {
to_boolean( Boolean &b ) : ref(b) {}
Boolean &ref;
};
struct to_octet {
to_octet( Octet &o ) : ref(o) {}
Octet &ref;
};
struct to_char {
to_char( Char &c ) : ref(c) {}
Char &ref;
};
Boolean operator>>=( to_boolean ) const;
Boolean operator>>=( to_octet ) const;
Boolean operator>>=( to_char ) const;
void replace( TypeCode_ptr tc, void *value,
Boolean release = CORBA_FALSE );
TypeCode_ptr type() const;
const void *value() const;
private:
TypeCode_ptr _tc; // データ型識別TypeCode
void *_value; // データ域アドレス
Boolean _release; // リリースフラグ
};
};以降では、以下のany型のIDL定義例をもとに、クライアント/サーバアプリケーションの記述例を示します。
module ODsample{
struct sample1 {
long para1;
string para2;
};
struct sample2 {
char para1;
float para2;
};
struct sample3 {
char para1;
double para2;
};
interface anytest{
any op1(in any any1, out any any2, inout any any3 );
};
};(2)クライアントアプリケーションで扱うパラメタ
クライアントアプリケーションのパラメタの扱いについて、以下に示します。
パラメタ | サーバへ渡すパラメタ | サーバから渡されたパラメタ |
|---|---|---|
in | 領域を動的に獲得する場合は、インスタンスをnewで生成します。 | - |
inout | (inパラメタと同じ) | 領域はスタブで自動的に獲得されます。 |
out | - | (inoutパラメタと同じ) |
クライアントおよびスタブで獲得した領域は、不要になった時点でdelete(C++演算子)で解放する必要があります。このとき、データ域(_value)を解放するかどうかをリリースフラグで指定します。リリースフラグの指定は、CORBA::Anyクラスのインスタンス生成時に3番目のパラメタで行います。
CORBA_TRUE : delete発行時、_valueの領域も解放される CORBA_FALSE : delete発行時、_valueの領域は解放されない(デフォルト)
なお、スタブで獲得されたパラメタ(inout,out,復帰)のリリースフラグは、CORBA_TRUEに設定されます。リリースフラグの詳細については、“4.5.12 any型、sequence型のリリースフラグ”を参照してください。
以下にクライアントアプリケーションの処理例を示します。
CORBA::Environment env;
ODsample::anytest_ptr obj;
ODsample::sample1 *smp1;
ODsample::sample2 *smp2;
ODsample::sample3 *smp3;
CORBA::Any *any0, *any1, *any2, *any3;
// inパラメタ
ODsample::sample2 *smp2 = new ODsample::sample2;
// データ域獲得(ODsample::sample2構造体)
smp2->para1 = 'z'; // データ域(構造体)設定
smp2->para2 = 0.001;
// インスタンス生成/パラメタ設定
any1 = new CORBA::Any( _tc_ODsample_sample2, smp2, CORBA_TRUE );
// inoutパラメタ
ODsample::sample3 *smp3 = new ODsample::sample3;
// データ域獲得(ODsample::sample3構造体)
smp3->para1 = 'x'; // データ域(構造体)設定
smp3->para2 = 0.0001;
any3 = new CORBA::Any(); // インスタンス生成
// パラメタ設定
any3->replace( _tc_ODsample_sample3, smp3, CORBA_TRUE);
// サーバ呼出し
any0 = obj->op1( *any1, any2, *any3, env );
// 領域解放
delete any0; // 復帰パラメタ
delete any1; // inパラメタ
delete any2; // outパラメタ
delete any3; // inoutパラメタ(3)サーバアプリケーションで扱うパラメタ
サーバアプリケーションのパラメタの扱いについて、以下に示します。
パラメタ | クライアントから渡されたパラメタ | クライアントへ渡すパラメタ |
|---|---|---|
in | 領域はスケルトンで自動的に獲得/解放されます。 | - |
inout | 領域はスケルトンで自動的に獲得されます。 | replaceメソッドでデータを置き換えます。 |
out | - | newで獲得します。 |
以下にサーバアプリケーションでの処理例を示します。
CORBA::Any*
ODsample_anytest_impl::op1(
const CORBA::Any &any1,
CORBA::Any *&any2,
CORBA::Any &any3,
CORBA::Environment &env )
throw( CORBA::Exception )
{
// outパラメタ
ODsample::sample1 *smp1 = new ODsample::sample1;
// データ域獲得(ODsample::sample1構造体)
smp1->para1 = 100; // データ域(構造体)設定
CORBA::Char *str = CORBA::string_alloc(3);
strcpy( str, "OUT" );
smp1->para2 = str;
// インスタンス生成/パラメタ設定
any2 = new CORBA::Any( _tc_ODsample_sample1, smp1, CORBA_TRUE);
// inoutパラメタ
ODsample::sample2 *smp2 = new ODsample::sample2;
// データ域獲得(ODsample::sample2構造体)
smp2->para1 = 'x'; // データ域(構造体)設定
smp2->para2 = 0.01;
// パラメタ設定
any3->replace( _tc_ODsample_sample2, smp2, CORBA_TRUE );
// 復帰値の処理
ODsample::sample3 *smp3 = new ODsample::sample3;
// データ域獲得(ODsample::sample3構造体)
smp3->para1 = 'z'; // データ域(構造体)設定
smp3->para2 = 0.001;
// インスタンス生成/パラメタ設定
CORBA::Any *any = new CORBA::Any( _tc_ODsample_sample3, smp3, CORBA_TRUE );
return( any );
}(4)CORBA::Anyクラスのメソッド
CORBA::Anyクラスで定義されているメソッドの意味を以下に示します。
CORBA::Anyクラスのメンバ | 意味 |
|---|---|
デフォルトコンストラクタ | インスタンス生成時、_tcを0、_valueを0で初期化します。リリースフラグにはCORBA_FALSEが設定されます。 |
コピーコンストラクタ | インスタンス生成時、データ域用の領域を獲得し、パラメタで指定された値を複写します。リリースフラグにはCORBA_TRUEが設定されます。 |
コンストラクタ (型定義されていない値用) | インスタンス生成時、パラメタで指定された値を_tcと_valueに設定します。リリースフラグは指定された値が設定されます。リリースフラグの指定を省略した場合はCORBA_FALSEが設定されます。 |
デストラクタ | リリースフラグがCORBA_TRUEの場合、_tcと_valueの値に対する領域を解放します。 |
代入演算子 | リリースフラグがCORBA_TRUEの場合、現在設定されている_tcと_valueの値に対する領域を解放します。その後、データ域用の領域を獲得し、パラメタで指定された値を設定します。リリースフラグにはCORBA_TRUEが設定されます。 |
左シフト代入演算子 | リリースフラグがCORBA_TRUEの場合、現在設定されている_tcと_valueの値に対する領域を解放します。その後、データ域用の領域を獲得し、パラメタで指定された値を設定します。リリースフラグにはCORBA_TRUEが設定されます。 |
右シフト代入演算子 | _valueに設定されている値を取り出します。 |
helper関数 | boolean,char,octetの場合、unsigned charになるので、これらの型を識別します。 |
replace関数 | リリースフラグがCORBA_TRUEの場合、現在設定されている_valueの値に対する領域を解放します。その後、パラメタで指定された値を_tcと_valueに設定します(新たに領域は獲得しません)。リリースフラグは指定された値が設定されます。リリースフラグの指定を省略した場合はCORBA_FALSEが設定されます。 |
type関数 | _tcのTypeCodeオブジェクトのオブジェクトリファレンスを返します。 |
value関数 | _valueに設定されているデータ域へのポインタをvoid*型で返します。 |
デフォルトコンストラクタは、_tcを0(TypeCode::_nil())、_valueを0で初期化し、また、リリースフラグをCORBA_TRUEに設定します。デフォルトコンストラクタの使用例と処理内容を以下に示します。
// 使用例
CORBA::Any a; // デフォルトコンストラクタで初期化
または
CORBA::Any *b = new CORBA::Any; // デフォルトコンストラクタで初期化
// デフォルトコンストラクタの処理内容
Any::Any()
{
_tc = TypeCode::_nil();
_value = 0;
_release = CORBA_TRUE;
}; コピーコンストラクタは、データ域用の領域を獲得し、パラメタで指定された値を複写します。リリースフラグにはCORBA_TRUEが設定されます。
コピーコンストラクタの使用例と処理内容を以下に示します。
// 使用例
CORBA::Any a; // デフォルトコンストラクタで初期化
CORBA::Long x = 3;
a <<= x; // 左シフト代入演算子。_tcに_tc_longを、
// _valueにCORBA::Longの領域を獲得し値3を設定、
// リリースフラグをCORBA_TRUEに設定
CORBA::Any *b = new CORBA::Any(a);
// コピーコンストラクタにより、aのprivateデータ(_tc,_value)のデータを複写し、
// また、リリースフラグをCORBA_TRUEに設定
if ( b->value() == NULL ) { // 領域の獲得の成否を判定
... // 獲得に失敗している場合、エラー処理
}
CORBA::Any c(*b); // コピーコンストラクタ
if ( c.value() == NULL ) { // 領域の獲得の成否を判定
... // 獲得に失敗している場合、エラー処理
}
// コピーコンストラクタの処理内容
Any::Any( const Any &a )
{
_tc = TypeCode::_duplicate(a.type());
_value = ... // 領域を獲得し、aの_valueデータを複写する処理
_release = CORBA_TRUE;
};このコンストラクタは、パラメタで指定したTypeCodeオブジェクトリファレンスtcの値をコピーし、valueの指すポインタを_valueに代入します。パラメタのreleaseがCORBA_TRUEであれば、デストラクタ起動時に_valueの指す領域は解放されます。release=CORBA_FALSEの場合は、アプリケーションが_valueでポイントされる領域を管理しなければなりません。
// 使用例
Long l = 1;
CORBA::Any *a = new CORBA::Any(tc_long, &l, CORBA_TRUE);
// 以下のコンストラクタが呼ばれます。
// コンストラクタの処理内容
Any::Any( TypeCode_ptr tc, void *value, Boolean release = CORBA_FALSE)
{
_tc = tc;
_value = value;
_release = release;
}デストラクタの使用例と処理内容を以下に示します。
// 使用例
void X()
{
CORBA::Any *a = new CORBA::Any();
CORBA::Long x = 3;
(*a) <<= x; // 左シフト代入演算子
delete a; // デストラクタ
}
// デストラクタの処理内容
Any::~Any()
{
if( _release && _value )
delete _value; // リリースフラグが設定されている場合には削除
CORBA::release( _tc );
}代入演算子の使用例と処理内容を以下に示します。
// 使用例
CORBA::Any a1; // デフォルトコンストラクタで初期化
CORBA::Any a2; // デフォルトコンストラクタで初期化
CORBA::Long x = 10;
a1 <<= x; // 左シフト代入演算子で、_tcに_tc_longを、
// _valueにCORBA::Longの領域を獲得し値10を、
// リリースフラグにCORBA_TRUEを設定
a2 = a1; // 代入演算子で、a2の_valueにCORBA::Longの領域を獲得し、
// a1のデータ(_tc,_value)の値をa2に複写し、
// リリースフラグにCORBA_TRUEを設定
if ( a2.value() == NULL ) { // 領域の獲得の成否を判定
... // 獲得に失敗している場合、エラー処理
}
// 代入演算子の処理内容
Any &
Any::operator=( const Any &r )
{
if( _release && _value )
delete value; // リリースフラグがCORBA_TRUEなら、既存データを削除
CORBA::release( _tc );
_tc = TypeCode::_duplicate(a.type());
_value = ... // 領域を獲得し、rの_valueの内容を複写する処理
_release = CORBA_TRUE;
return this;
}左シフト代入演算子の使用例と処理内容を以下に示します。
// 使用例
CORBA::Long value = 42;
Any a;
a <<= value; // _tcに_tc_longを、_valueにCORBA::Longの領域を獲得し値42を、
// リリースフラグにCORBA_TRUEを設定
if ( a.value() == NULL ) { // 領域の獲得の成否を判定
... // 獲得に失敗している場合、エラー処理
}
// 左シフト代入演算子の処理内容
void CORBA::Any::operator<<=( Long v )
{
if( _release && _value )
delete value; // リリースフラグがCORBA_TRUEなら、既存データを削除
CORBA::release( _tc );
_tc = .... ( _tc_longを設定する処理)
_value = new Long(v); // _valueにvの値を設定
_release = CORBA_TRUE;
}右シフト代入演算子の使用例と処理内容を以下に示します。
// 使用例
CORBA::Long value;
Any a;
a <<= CORBA::Long(42); // aの_tcに_tc_longを_valueに値42を代入
// リリースフラグはCORBA_TRUEを設定
if(a >>= value ) {
// aの_tcが_tc_longを指している場合には、CORBA_TRUEを返し、
// valueに_valueの値を代入。
}
// 右シフト代入演算子の処理内容
CORBA::Boolean
CORBA::Any::operator>>=( Long &r )const
{
if( _tc->kind != tk_long ) // _tcがtc_longを指しているかチェック
return CORBA_FALSE
r = ... // _valueの値を代入する処理
return CORBA_TRUE;
}文字列と配列に関して取り出された値を使うときは、文字列または配列のサイズ指定を超えてはいけないので、アプリケーションはAny型のTypeCodeをチェックしなければなりません。
boolean、char、octetがすべてC++でunsigned charにマッピングされるので、以下のように、直接Any型変数にboolean、octet、char型の変数を代入または取り出しを行うとコンパイルエラーになります。
Octet oct = 040; Any any; any <<= oct; // この行はコンパイルが通らない
boolean, char, octetを区別する方法としてhelper関数と、operator<<=とoperator>>=が提供されます。helper関数の使用例を以下に示します。
CORBA::Boolean b = CORBA_TRUE;
Any any;
any <<= CORBA::Any::from_boolean(b); // _tcに_tc_booleanを、_valueにbの値を代入
...
if( any >>= CORBA::Any::to_boolean(b)){
// anyの_valueはCORBA::Boolean型
// bにanyの_valueの値(ここではCORBA_TRUE)を代入
}replace関数は、パラメタで指定したTypeCodeオブジェクトリファレンスtcと値valueを_tcと_valueに代入します。パラメタのreleaseがCORBA_TRUEであれば、デストラクタ起動時に、_valueの指す領域を解放します。release=CORBA_FALSEの場合は、アプリケーションが_valueでポイントされる領域を解放しなければなりません。
// 使用例
Long l = 1;
CORBA::Any *a = new CORBA::Any();
a->replace(_tc_long, &l, CORBA_FALSE); // 以下の関数が呼ばれます。
// replace関数の処理内容
Any::Any::replace( TypeCode_ptr tc, void *value, Boolean release = CORBA_FALSE)
{
if( _release && _value )
delete value; // リリースフラグがCORBA_TRUEなら、既存データを削除
CORBA::release( _tc );
_tc = tc;
_value = value;
_release = release;
}