(1)IDLマッピング
IDL言語でシーケンス型sequenceを指定した場合、C++言語では、配列の最大個数(_maximum)、配列の使用個数(_length)、データ域のアドレス(_buffer)、リリースフラグ(_release)をprivateデータに持つクラス(シーケンスクラス)にマッピングされます。また、データ域(_buffer)の獲得関数(関数名は“モジュール名::インタフェース名::シーケンス名::allocbuf”。以降XX::allocbuf関数と呼ぶ)が生成されます。
シーケンスクラスのインスタンスはnew(C++の演算子)で生成します。パラメタには、配列の最大個数、使用個数、データ域のアドレス(XX::allocbuf関数で獲得)、リリースフラグを指定します。
以降では、以下のIDL定義例をもとに説明します。
module ODsample{ interface seqtest{ typedef sequence<long> sampleseq; sampleseq op1(in sampleseq seq1, out sampleseq seq2, inout sampleseq seq3 ); }; };
class sampleseq { public: sampleseq(); // デフォルトコンストラクタ sampleseq( CORBA::ULong max); // maximumコンストラクタ sampleseq( CORBA::ULong max, CORBA::ULong length, CORBA::Long *data, CORBA::Boolean release = CORBA_FALSE ); // T *dataコンストラクタ sampleseq( const sampleseq &s ); // コピーコンストラクタ ~sampleseq(); // デストラクタ static CORBA::Long *allocbuf( CORBA::ULong ); // allocbuf static void freebuf( CORBA::Long* ); // freebuf sampleseq &operator=( const sampleseq &s ); // 代入演算子 CORBA::ULong maximum() const; // maximumアクセス関数 void length( CORBA::ULong ); // lengthアクセス関数 CORBA::ULong length() const; // lengthアクセス関数 CORBA::Long &operator[]( CORBA::ULong index ); // _bufferのindex番目の要素を取得 const CORBA::Long &operator[]( CORBA::ULong index ) const; // _bufferのindex番目の要素を取得 private: CORBA::ULong _maximum; // 配列の最大個数 CORBA::ULong _length; // 配列の個数 CORBA::Long *_buffer; // 配列の値 CORBA::Boolean _release; // リリースフラグ };
// 左シフト代入演算子 void operator<<=( CORBA::Any&, const ODsample::seqtest::sampleseq& ); void operator<<=( CORBA::Any&, ODsample::seqtest::sampleseq* ); void operator<<=( CORBA::Any_var&, const ODsample::seqtest::sampleseq& ); // 右シフト代入演算子 CORBA::Boolean operator>>=( const CORBA::Any&, ODsample::seqtest::sampleseq*& ); CORBA::Boolean operator>>=( const CORBA::Any_var&, ODsample::seqtest::sampleseq*& );
(2)クライアントアプリケーションで扱うパラメタ
クライアントアプリケーションのパラメタの扱いについて、以下に示します。
パラメタ | サーバへ渡すパラメタ | サーバから渡されたパラメタ |
---|---|---|
in | 領域を動的に獲得する場合、シーケンスクラスのインスタンスはnew演算子を使用し、データ域はXX::allocbuf関数を使用します。 | - |
inout | シーケンスクラスのインスタンスを動的に獲得する場合はnew演算子を使用します。データ域を獲得する場合はXX::allocbuf関数を使用します。 リリースフラグにはCORBA_TRUEを設定してください。データ域はスタブで自動的に解放されます。 | 領域はスタブで自動的に獲得されます(構造体メンバも設定されます)。この際、獲得した領域にはリリースフラグにCORBA_TRUEが設定されます。 |
out | - | (inoutパラメタと同じ) |
クライアントおよびスタブで獲得した領域は、不要になった時点でdelete(C++演算子)で解放する必要があります。このとき、データ域(_buffer)を解放するかどうかをリリースフラグで指定します。リリースフラグの指定は、シーケンスクラスのインスタンス生成時に4番目のパラメタで行います。
CORBA_TRUE : delete発行時、_bufferの領域も解放される。 CORBA_FALSE : delete発行時、_bufferの領域は解放されない。(デフォルト)
なお、スタブで獲得されたパラメタ(inout,out,復帰)のリリースフラグは、CORBA_TRUEに設定されます。リリースフラグの詳細については、“4.5.12 any型、sequence型のリリースフラグ”を参照してください。
以下にクライアントアプリケーションの処理例を示します。
ODsample::sampleseq *seq = new ODsample::sampleseq( CORBA::ULong maximum, CORBA::ULong minimum, CORBA::Long *data, CORBA::Boolean release = CORBA_FALSE ); CORBA::Environment env; ODsample::seqtest_ptr obj; ODsample::sampleseq *seq0, *seq1, *seq2, *seq3; // inパラメタ CORBA::Long *p = ODsample::seqtest::sampleseq::allocbuf(3); // データ域獲得 for( int i = 0; i < 3; i++ ) // データ域設定 p[i] = i*10; // インスタンス生成/パラメタ設定 seq1 = new ODsample::seqtest::sampleseq( 3, 3, p, CORBA_TRUE ); // inoutパラメタ CORBA::Long *q = ODsample::seqtest::sampleseq::allocbuf(5); // データ域獲得 for( i = 0; i < 5; i++ ) // データ域設定 q[i] = i*100; // インスタンス生成/パラメタ設定 seq3 = new ODsample::seqtest::sampleseq( 5, 5, q, CORBA_TRUE ); // サーバ呼出し seq0 = obj->op1( obj, *seq1, seq2, *seq3, env ); // 領域解放 delete seq0; // 復帰パラメタ delete seq1; // inパラメタ delete seq2; // outパラメタ delete seq3; // inoutパラメタ
(3)サーバアプリケーションで扱うパラメタ
サーバアプリケーションのパラメタの扱いについて、以下に示します。
パラメタ | クライアントから渡されたパラメタ | クライアントへ渡すパラメタ |
---|---|---|
in | 領域はスケルトンで自動的に獲得/解放されます。 | - |
inout | 領域はスケルトンで自動的に獲得されます。この際、リリースフラグにはCORBA_TRUEが設定されます。 | inoutデータの領域を更新する場合には、代入演算子でデータを複写します。 |
out | - | シーケンスクラスのインスタンスをnew演算子で、データ域をXX::allocbuf関数で獲得します。 |
以下にサーバアプリケーションでの処理例を示します。
ODsample::seqtest::sampleseq* ODsample_seqtest_impl::op1( const ODsample::seqtest::sampleseq &seq1, ODsample::seqtest::sampleseq *&seq2, ODsample::seqtest::sampleseq &seq3, CORBA::Environment &env ) throw( CORBA::Exception ) { // outパラメタ CORBA::Long *p = ODsample::seqtest::sampleseq::allocbuf(2); // データ域獲得 for( int i = 0; i < 2; i++ ) // データ域設定 p[i] = i*1000; // インスタンス生成/パラメタ設定 seq2 = new ODsample::seqtest::sampleseq( 2, 2, p, CORBA_TRUE ); // inoutパラメタ CORBA::Long *q = ODsample::seqtest::sampleseq::allocbuf(3); // データ域獲得 for( i = 0; i < 3; i++ ) // データ域設定 q[i] = i; // 代入演算子でパラメタ設定 seq3 = ODsample::seqtest::sampleseq( 3, 3, q, CORBA_TRUE ); // 復帰パラメタ CORBA::Long *r = ODsample::seqtest::sampleseq::allocbuf(1); r[0] = 0; // データ域獲得/設定 // インスタンス生成/パラメタ設定 ODsample::seqtest::sampleseq_ptr seq = new ODsample::seqtest::sampleseq( 1, 1, r, CORBA_TRUE ); return seq; }
(4)シーケンスクラスのメソッド
シーケンスクラスで定義されているメソッドとその意味を以下に示します。
メソッド | 意味 |
---|---|
デフォルトコンストラクタ | インスタンス生成時、シーケンス長_lengthを0で初期化します。また、サイズ指定なしのシーケンスの場合、最大長_maximumも0で初期化し、リリースフラグはCORBA_FALSEに設定します。サイズ指定ありのシーケンスの場合、最大長_maximumはIDLの定義値で初期化され、リリースフラグはCORBA_TRUEに設定します。 |
コピーコンストラクタ | インスタンス生成時、_bufferの領域を獲得し、パラメタで指定された値を_length、_maximum、_bufferに設定します。リリースフラグはCORBA_TRUEに設定します。 |
maximumコンストラクタ | サイズ指定なしのシーケンスの場合のみ提供されます。インスタンス生成時、パラメタで指定された値を_maximumに設定します。また、_bufferの領域を獲得します。リリースフラグはCORBA_TRUEに設定します。 |
T*dataコンストラクタ | インスタンス生成時、サイズ指定あり/なしの両方で、パラメタで指定したシーケンス長、最大長、バッファポインタおよびリリースフラグを_length、_maximum、_buffer、_releaseに設定します。リリースフラグの指定を省略した場合はCORBA_FALSEを設定します。 |
デストラクタ | リリースフラグがCORBA_TRUEの場合、_bufferの値に対する領域をfreebuf関数で解放します。 |
代入演算子 | リリースフラグがCORBA_TRUEの場合、_bufferの値に対する領域をfreebuf関数で解放します。データ域の領域を獲得し代入元のデータを複写します。リリースフラグはCORBA_TRUEに設定します。 |
添字演算子 | 与えられたインデックスに対応する_bufferの内容を返します。 |
maximumアクセス関数 | サイズ指定のないシーケンスの場合、現在使用可能なバッファの総数を返します。サイズが指定されたシーケンスの場合、IDLで与えられたシーケンスの大きさを返します。 |
lengthアクセス関数 | length(ULong)関数はパラメタで指定した値をシーケンス長に設定します。この際、必要に応じて_bufferの領域を獲得します。メモリ不足により領域の獲得に失敗した場合、シーケンスの値(シーケンス長、_buffer)は変更されません。 |
allocbuf関数 | T*dataコンストラクタに渡すことができるシーケンスの要素の配列を割り当てます。 |
freebuf関数 | allocbuf関数によって割り当てられた配列を解放します。 |
左シフト代入演算子 | AnyまたはAny_varへのシーケンスの代入を行います。Any変数のリリースフラグにはCORBA_TRUEを設定します。 |
右シフト代入演算子 | AnyまたはAny_varからシーケンスへのポインタの取り出しを行います。 |
サイズ指定あり/なしの両方で、デフォルトコンストラクタはシーケンス長を0に初期化します。サイズ指定ありでは最大長はメンバイニシャライザで初期化されるので、アプリケーションは変更できません。サイズ指定なしのシーケンスでは、デフォルトコンストラクタで最大長を0に初期化します。サイズ指定ありのシーケンスではリリースフラグはCORBA_TRUEに設定され、サイズ指定なしのシーケンスではリリースフラグはCORBA_FALSEに設定されます。また、サイズ指定ありのシーケンスでは_bufferの領域が獲得されます。なお、メモリ不足により領域の獲得に失敗した場合、_bufferはNULLに設定されます。このため、メモリ不足が発生する可能性がある環境でサイズ指定ありのシーケンスを使用する場合は、デフォルトコンストラクタ以外のコンストラクタの使用を推奨します。
デフォルトコンストラクタの使用例と処理内容を以下に示します。
// IDL typedef sequence< long > LongSeq1; // サイズ指定なしの場合 typedef sequence< long, 10 > LongSeq2; // サイズ指定あり(この例では10)の場合 //使用例 LongSeq1 *seq1 = new LongSeq1(); // 以下のデフォルトコンストラクタLongSeq1()が呼ばれ // seq1 が初期化されます。 LongSeq2 *seq2 = new LongSeq2(); // 以下のデフォルトコンストラクタLongSeq2()が呼ばれ // seq2 が初期化されます。 // デフォルトコンストラクタ (サイズ 指定なし) LongSeq1::LongSeq1() { _length = 0; _maximum = 0; _release = CORBA_FALSE; } // デフォルトコンストラクタ(サイズ 指定あり) LongSeq2::LongSeq2() : _maximum(10) // IDLで指定したサイズ { _length = 0; _buffer = LongSeq2::allocbuf(10); _release = CORBA_TRUE; }
コピーコンストラクタは、パラメタで指定されたシーケンスと同じ最大長と長さを持つ新しいシーケンスを生成し、パラメタで指定されたシーケンスの要素データをコピーします。コピーコンストラクタでは、リリースフラグはCORBA_TRUEに設定されます。
なお、コピーコンストラクタでは_bufferの領域が獲得されます。メモリ不足により領域の獲得に失敗した場合、サイズ指定なしのシーケンスでは_lengthと_maximumが0に設定され、_bufferがNULLに設定されます。サイズ指定ありのシーケンスでは_lengthが0に設定され、_bufferがNULLに設定されます。
コピーコンストラクタの使用例と処理内容を以下に示します。
// 使用例 long data[] = {1, 2, 3, 4, 5}; LongSeq s1(10, 5, data); LongSeq s2(s1) // 以下のコピーコンストラクタが呼ばれs1の // データがs2にコピーされます if ( s2.length() == 0 ) { // 領域の獲得の成否を判定(_lengthが0の場合、失敗) ... // 獲得に失敗している場合、エラー処理 } // コピーコンストラクタ LongSeq::LongSeq( const LongSeq &s ) { _length = s.length(); _maximum = s.maximum(); _buffer = allocbuf( _maximum ); for( int i = 0; i < _length; i++ ) // s の内容から *( _buffer + i ) へのコピー _release = CORBA_TRUE; }
サイズ指定なしのシーケンスでは、最大長として指定された個数分の_bufferの領域を獲得するコンストラクタが提供されます。maximumコンストラクタはリリースフラグをCORBA_TRUEに設定します。なお、メモリ不足により_bufferの領域獲得に失敗した場合、_maximumが0に設定され、_bufferがNULLに設定されます。
maximumコンストラクタの使用例と処理内容を以下に示します。
// IDL typedef sequence< long > LongSeq; // 使用例 LongSeq seq(10); // 以下のmaximumコンストラクタ が呼ばれ // seq の最大長が10に設定されます if ( seq.maximum() == 0 ) { // 領域の獲得の成否を判定(_maximumが0の場合、失敗) ... // 獲得に失敗している場合、エラー処理 } // maximumコンストラクタ LongSeq::LongSeq(ULong max) { _maximum = max; _buffer = LongSeq::allocbuf(max); release = CORBA_TRUE; }
T*dataコンストラクタは、サイズ指定あり/なしの両方で、パラメタで指定した値をprivateデータに設定します。サイズ指定のないシーケンスに対しては最大長の設定も可能です。
このコンストラクタは、releaseパラメタによって_bufferの扱いが異なります。パラメタがCORBA_FALSEである場合は、_bufferの指す領域はアプリケーションが管理する必要があります。一方、CORBA_TRUEである場合は、_bufferの指す領域はシーケンスクラスの変数が解放されるときに解放されます。T*dataコンストラクタの使用例と処理内容を以下に示します。
// 使用例 long data[] = {1, 2, 3, 4, 5}; LongSeq seq = new LongSeq(10, 5, data); // 以下のT *dataコンストラクタ が呼ばれseq が初期化されます // T *dataコンストラクタ LongSeq::LongSeq( ULong max, ULong length, Long *value, Boolean release = CORBA_FALSE ) { _length = length; _maximum = max; _buffer = value; _release = release; }
T *dataコンストラクタで指定するvalueの値がString型の場合はString_var*を渡し、オブジェクトリファレンス型の場合はObject_var*を渡します。
ODsample::seqtest::sampleseq::~sampleseq() { if( _release == CORBA_TRUE ) ODsample::seqtest::sampleseq::freebuf( _buffer ); }
代入演算子は、リリースフラグがCORBA_TRUEに設定されている場合は_bufferの指す領域を解放します。リリースフラグがCORBA_FALSEに設定されている場合は、解放は行いません。その後、_bufferの領域を新規に獲得し、パラメタで指定されたシーケンスの要素データをコピーします。なお、メモリ不足により領域の獲得に失敗した場合、サイズ指定なしのシーケンスでは_lengthと_maximumが0に設定され、_bufferがNULLに設定されます。サイズ指定ありのシーケンスでは_lengthが0に設定され、_bufferがNULLに設定されます。
代入演算子ではリリースフラグはCORBA_TRUEに設定されます。代入演算子の処理内容を以下に示します。
// 使用例 long data[] = {1, 2, 3, 4, 5}; LongSeq s1(10, 5, data); LongSeq s2; LongSeq s2 = s1; // 以下の代入演算子が呼ばれ、s1のデータがs2にコピーされます if ( s2.length() == 0 ) { // 領域の獲得の成否を判定(_lengthが0の場合、失敗) ... // 獲得に失敗している場合、エラー処理 } // 代入演算子 LongSeq & LongSeqV1::operator=( const LongSeqV1 &s ) { if( _release ) LongSeq::freebuf( _buffer ); _length = s.length(); _maximum = s.maximum(); _buffer = LongSeq::allocbuf( _maximum ); for( int i = 0; i < _length; i++ ) // *( _buffer + i ) へ s[i] をコピー _release =CORBA_TRUE; return *this; }
添字演算子は、与えられたインデックスに対応する_bufferの内容を返します。添字演算子の使用例を以下に示します。
// 使用例 Long l; long data[] = {1, 2, 3, 4, 5}; LongSeq seq(10, 5, data,CORBA_TRUE); l = seq[3]; // lの値は4
シーケンスの要素がString型の場合はString_varが返され、オブジェクトリファレンス型の場合はObject_var型が返されます。
サイズ指定のないシーケンスに対するmaximum()アクセス関数は、現在使用可能なバッファの総数を返します。アプリケーションは、サイズ指定のないシーケンスにどのくらいのアイテムが設定できるかを知ることができます。サイズが指定されたシーケンスに対するmaximum()はそのIDLで与えられたシーケンスの大きさを返します。maximumアクセス関数の使用例を以下に示します。
// IDL typedef sequence< long > LongSeq1; typedef sequence< long, 10 > LongSeq2; // 使用例 Long l; LongSeq1 s1(5); LongSeq2 s2; l = s1.maximum(); // l の値は5 l = s2.maximum(); // l の値は10
length(ULong)関数はパラメタで指定した値をシーケンス長に設定し、また、_bufferにlength分の領域を獲得します。メモリ不足により領域の獲得に失敗した場合、シーケンスの値(シーケンス長、_buffer)は変更されません。
length()はシーケンス長を返します。
lengthアクセス関数の使用例を以下に示します。
// 使用例 Long l; long data[] = {1, 2, 3, 4, 5}; LongSeq s1 = new LongSeq(10, 5, data, CORBA_FALSE); l = s1->length(); // lの値は5 s1->length(6); // シーケンス長を6 に設定 if ( s1->length() == l ) { // 領域の獲得の成否を判定(_lengthが変更されていない場合、失敗) ... // 獲得に失敗している場合、エラー処理 }
allocbuf関数はT*dataコンストラクタに渡すことができるシーケンスの要素の配列を割り当てます。配列の長さはパラメタにより与えられます。使用例を以下に示します。
// 使用例 Long *data = LongSeq::allocbuf(3); data[0] = 0; data[1] = 1; data[2] = 2; LongSeq *seq = new LongSeq(10, 3, data, CORBA_TRUE); if ( seq == NULL ) { // 領域の獲得の成否を判定 ... // 獲得に失敗している場合、エラー処理 }
allocbuf関数は要求されたメモリを割り当てられない場合はNULLポインタを返します。allocbuf関数によって割り当てられた配列は、リリースフラグがCORBA_TRUEの場合には、sequence解放時に、デストラクタにより解放されます。リリースフラグがCORBA_FALSEの場合にはfreebuf関数によって、アプリケーションにより解放しなければなりません。
左シフト代入演算子はAnyの_valueにシーケンスのコピーまたはポインタを代入します。このとき、AnyのリリースフラグにはCORBA_TRUEが設定されます。
シーケンスのコピーを代入する場合、Anyの_valueの領域が新規に獲得されます。領域の獲得に失敗した場合、_valueはNULLに設定されます。
シーケンスのコピーの代入は、Any_varに対しても実行できます。使用例を以下に示します。
// 使用例 long data1[] = {1, 2, 3, 4, 5}; ODsample::seqtest::sampleseq *seq1 = new ODsample::seqtest::sampleseq( 10, 5, data1 ); CORBA::Any a1; a1 <<= *seq1; // a1の_valueにseq1のコピーを設定 // TypeCodeに_tc_ODsample_seqtest_sampleseq、リリースフラグにCORBA_TRUEを設定 if ( a1.value() == NULL ) { // 領域の獲得の成否を判定 ... // 獲得に失敗している場合、エラー処理 } long data2[] = {1, 2, 3, 4}; ODsample::seqtest::sampleseq *seq2 = new ODsample::seqtest::sampleseq( 10, 4, data2 ); CORBA::Any a2; a2 <<= seq2; // a2の_valueにseq2のポインタを設定 // TypeCodeに_tc_ODsample_seqtest_sampleseq、リリースフラグにCORBA_TRUEを設定 // seq2を解放後は、a2の_valueにはアクセス不可 long data3[] = {1, 2, 3}; ODsample::seqtest::sampleseq *seq3 = new ODsample::seqtest::sampleseq( 10, 3, data3 ); Any a3; Any_var a3_v( &a3 ); a3_v <<= *seq3; // a3の_valueにseq3のコピーを設定 // TypeCodeに_tc_ODsample_seqtest_sampleseq、リリースフラグにCORBA_TRUEを設定
if ( a3.value() == NULL ) { // 領域の獲得の成否を判定 ... // 獲得に失敗している場合、エラー処理 }
右シフト代入演算子はAnyの_valueに設定されているシーケンスを取り出します。引数としてシーケンスのポインタを設定します。AnyのTypeCodeが引数のTypeCodeと等しければ_valueの値を引数に代入し、CORBA_TRUEで復帰します。
右シフト代入演算子はAny_varに対しても使用できます。使用例を以下に示します。
// 使用例 long data[] = {1, 2, 3, 4, 5}; ODsample::seqtest::sampleseq *seq1 = new ODsample::seqtest::sampleseq (10, 5, data); Any a; a <<= *seq1; // aの_valueにseq1のコピーを設定 // TypeCodeに_tc_ODsample_seqtest_sampleseq、リリースフラグにCORBA_TRUEを設定 ODsample::seqtest::sampleseq *seq2, *seq3; if( a >>= seq2 ){ // aのTypeCodeが_tc_ODsample_seqtest_sampleseqの場合、 // CORBA_TRUEを返し、seq2にaの_valueの値(seq1)を代入 } Any_var a_var( &a ); if( a_var >>= seq3 ){ // aのTypeCodeが_tc_ODsample_seqtest_sampleseqの場合、 // CORBA_TRUEを返し、seq3にaの_valueの値(seq1)を代入 }