表13-1に示すように、OMG IDL文の基本データ型は、CORBAモジュールのC++ typedefにマッピングされます。
表13-2に、オブジェクト、擬似オブジェクト、およびユーザー定義型のマッピングを示します。
OMG IDLの文字列は、C++のchar *にマッピングされます。
char *には、制限付き文字列と無制限文字列の両方がマッピングされます。C++のCORBA文字列は、NULLで終了し、char *
型の使用時には常に使用できます。
structなど、他のユーザー定義の型の中に文字列がある場合は、
CORBA::String_var型にマッピングされます。これにより、構造体内の各メンバーは自身のメモリーを管理できます。
注意:
|
string_alloc関数によって len+1文字が割り当てられるので、結果として得られた文字列には後続のNULL文字の保持に十分なスペースを確保できます。
|
注意:
|
wcharおよび wstringデータ型を使用すると、ユーザーが記述するネイティブ言語でコンピュータと対話できます。日本語や中国語など、言語によっては一意の文字が多数ある言語もあります。このような文字セットは、1バイトの中に収まりません。マルチ・バイト文字セットをサポートするために様々なスキームが考案されていますが、まだ実用的なレベルには至っていません。ワイド文字とワイド文字列を使用すると、こういった複雑な文字セットとのやり取りが容易になります。
|
wstringデータ型は、ワイド文字NULLを除き
wcharのシーケンスを表します。
wstring型はstring型と似ていますが、その要素型が
charではなく
wcharである点で異なります。
wstringの実際の長さは実行時に設定されます。制限付き形式を使用する場合、長さは制限以下でなければなりません。
次に、wstringのサンプル・コードを示します。
wstring型は、unsigned long、char、string、doubleなどの型とまったく同様にビルドされます。これらの型は、パラメータとして直接使用したり、typedefで指定したり、構造体、シーケンス、ユニオン、配列などの作成に使用したりできます。
注意:
|
wcharおよび wstringデータ型を使用すると、ユーザーが記述するネイティブ言語でコンピュータと対話できます。日本語や中国語など、言語によっては一意の文字が多数ある言語もあります。このような文字セットは、1バイトの中に収まりません。マルチ・バイト文字セットをサポートするために様々なスキームが考案されていますが、まだ実用的なレベルには至っていません。ワイド文字とワイド文字列を使用すると、こういった複雑な文字セットとのやり取りが容易になります。
|
最上位の定数は、生成された.hインクルード・ファイルで初期化されます。ただし、モジュールとインタフェースの各定数は、生成されたクライアント・スタブ・モジュールで初期化されます。
ユニオン・メンバーのデータ型によっては、モディファイア関数が追加生成されます。各データ
型に対して生成されるメンバー関数は次のとおりです。
•
|
オブジェクトおよび擬似オブジェクト
メンバー名がobjtypeのオブジェクト型およびTypecode型の場合、メンバー関数は次のように生成されます。 void objtype (TYPE); // modifier TYPE objtype () const; // accessor
OMG IDLのデータ型からC++のデータ型 TYPEへのマッピングについては、 表13-1を参照してください。 モディファイア・メンバー関数では、指定されたオブジェクト参照引数の所有権を想定していません。代わりに、モディファイアはオブジェクト参照または擬似オブジェクト参照を複製します。リファレンスが不要になったときは、リファレンスを解放してください。
|
•
|
Enum
メンバー名がenumtypeのenum TYPEの場合、メンバー関数は次のように生成されます。 void enumtype (TYPE); // modifier TYPE enumtype () const; // accessor
|
•
|
文字列
文字列の場合、次に示すようにアクセサ関数が1つとモディファイア関数3つが生成されます。
void stringInfo (char *); // modifier 1 void stringInfo (const char *); // modifier 2 void stringInfo (const CORBA::String_var &); // modifier 3 const char * stringInfo () const; // accessor
最初のモディファイアでは、渡された char *パラメータの所有権を想定しており、ユニオンの値が変更されるかユニオンが破棄されたときに、ユニオンはこの文字列に対して CORBA::string_freeメンバー関数を呼び出します。 2番目と3番目のモディファイアでは、パラメータに渡されるか、または文字列varに格納されている指定の文字列をコピーします。 アクセサ関数は、ユニオンの内部メモリーへのポインタを戻します。また、このメモリーの解放を試行せず、ユニオンの値が変更されるかユニオンが破棄された後は、このメモリーにアクセスしません。
|
TYPE( const TYPE & From);
TYPE &operator=(const TYPE & From);
ユニオンの新しいインスタンスで_d()モディファイアが呼び出されると、Tuxedo C++の「暗黙的な切替」の制約が緩和されます。この場合、例外はスローされず、ユニオンへの影響はありません。
operator[]関数は、シーケンス要素へのアクセスまたはシーケンス要素の変更に使用します。この演算子は、シーケンス要素にリファレンスを返します。OMG IDLのベース・タイプは、C++の適切なデータ型にマッピングされます。
基本データ型については、表13-1を参照してください。オブジェクト参照、TypeCodeリファレンス、および文字列の場合、ベース・タイプは生成された
_ForSeq_varクラスにマッピングされます。
_ForSeq_varクラスは、文字列またはシーケンス内に格納されたオブジェクトを更新する機能を備えています。このクラスには、対応するvarクラスと同じメンバー関数とシグネチャがあります。ただし、
_ForSeq_varクラスは、シーケンス・コンストラクタのreleaseパラメータの設定に従います。ほかのクラスとの相違点は、
_ForSeq_varクラスの場合、ユーザーが
Releaseフラグを指定できるので、メモリーの解放を制御できることです。
次では、ベース・タイプがTYPEで指定のOMG IDLシーケンスが
SEQの場合に、生成されるシーケンス・クラスのメンバー関数について説明します。
要素を解放するかどうかを指定します。このフラグの値がCORBA_TRUEの場合、シーケンスは
Value引数が指すバッファの所有権を想定します。
Releaseフラグが
CORBA_ TRUEの場合、このバッファは
allocbufメンバー関数で割り当てる必要があります。これは、シーケンスの破棄時に、このバッファを
freebufメンバー関数で解放するためです。
この関数は、シーケンスの現在の長さを設定します。Length引数には、シーケンスの新しい長さを指定します。シーケンスが無制限で新しい長さが現在の最大値を超える場合、バッファが再割り当てされ、要素が新しいバッファにコピーされます。新しい長さが最大値を超える場合、最大値は新しい長さに設定されます。
TYPE & operator[](CORBA::ULong Index);
const TYPE & operator[](CORBA::ULong Index) const;
前述のアクセサ関数は、指定の索引でシーケンス要素への参照を返します。Index引数には、戻り値となる要素の索引を指定します。この索引は、現在のシーケンスの長さを超えることはできません。長さは、
TYPE *コンストラクタまたは
length(CORBA::ULong)モディファイアで設定済ある必要があります。
TYPEがオブジェクト参照、TypeCodeリファレンス、または文字列の場合、戻り値の型は
ForSeq_varクラスになります。
static TYPE * allocbuf(CORBA::ULong NumElems);
この静的関数は、TYPE *コンストラクタで使用されるバッファを割り当てます。NumElems引数には、バッファ内の割り当てる要素数を指定します。バッファの割当てができない場合、NULLが返されます。
static TYPE_slice * TYPE_alloc(void);
この関数は、TYPE配列を割り当て、割当て済
TYPE配列へのポインタを返します。配列を動的に割り当てることができない場合、0(ゼロ)を返します。
static TYPE * _narrow(CORBA::Exception_ptr Except);
この関数は、例外がTYPE例外にナロー変換できる場合に、
TYPE例外へのポインタを返します。例外がナロー変換できない場合は、0(ゼロ)を返します。
TYPEポインタは、新しいクラスへのポインタではなく、 元の例外ポインタへの型付きポインタです。これは、Exceptパラメータが有効なかぎりにおいて有効です。
TYPE (const TYPE & From);
TYPE & operator=(const TYPE & From);
•
|
通常の場合ではOMG IDLで許可されていない、他のサーバーレス・オブジェクト型 1を宣言で参照する場合があります。
|
pseudo接頭辞は、そのインタフェースが通常の方法またはサーバーレスの方法のどちらかで実装されることを示します。つまり、以降のセクションで説明する規則か、またはこの章で説明する通常のマッピング規則のどちらかを適用することになります。
•
|
_duplicateの有効な実装では、単純に引数を返すか、または新しいインスタンスへの参照を作成します。個別に実装を行うことで、動作の確実性が高くなることがあります。
|
ObjectIdを文字列に変換したときに、文字列に正しくない文字(NULLなど)が生成された場合は、最初の2つの関数によって
CORBA::BAD_PARAM例外がスローされます。
インタフェースINTFの場合、生成されるインタフェース・コードには、次の項目が格納されます。
static INTF_ptr _duplicate (INTF_ptr Obj)
この静的メンバー関数は、既存のINTFオブジェクト参照を複製して、新しい
INTFオブジェクト参照を返します。新しい
INTFオブジェクト参照は、
CORBA::releaseメンバー関数を呼び出して解放する必要があります。エラーが発生した場合、nil
INTFオブジェクトへのリファレンスが返されます。引数
Objには、複製元のオブジェクト参照を指定します。
static INTF_ptr _narrow (CORBA::Object_ptr Obj)
INTF_ptrオブジェクト参照は、
INTFオブジェクト、または
INTFオブジェクトを継承するオブジェクトと対応している必要があります。新しい
INTFオブジェクト参照は、
CORBA::releaseメンバー関数を呼び出して解放する必要があります。引数
Objには、
INTFオブジェクト参照にナロー変換されるオブジェクト参照を指定します。
Objパラメータは、このメンバー関数では変更されません。また、不要になったときは解放してください。
Objが
INTFオブジェクト参照にナロー変換できない場合は、
INTF nilオブジェクト参照が返されます。
この静的メンバー関数は、INTFインタフェースの新しいnilオブジェクト参照を返します。新しいリファレンスは
、
CORBA::releaseメンバー関数を呼び出して解放する必要はありません。
かわりに、オブジェクト参照の型、INTF_ ptrクラス、または
INTF_varクラスのいずれかを使用します。
オブジェクト参照を取得するには、
_narrow静的メンバー関数を使用します。これらのクラスで操作を呼び出すには、矢印演算子(
->)を使用します。
INTF_varクラスは、
INTF_varクラスがスコープをはずれるか、または再割り当てされるときに、オブジェクト参照を自動的に解放することでメモリー管理を簡単にします。変数の型は、多くのUDTに対して生成されます。
「varクラスの使い方」では、変数の型について説明しています。
OMG IDLのanyは、
CORBA::Anyクラスにマッピングされます。
CORBA::Anyクラスは、型保障の方法でC++の型を処理します。
一致しないTypeCodeや値でanyが作成される可能性を低くするには、C++関数のオーバーロード機能を使用します。具体的には、OMG IDL仕様の特定の型ごとに、その型の値を挿入および抽出するためのオーバーロード関数が用意されています。ネームスペースの純粋さが損なわれるのを完全に防ぐには、これらの関数にオーバーロード演算子を使用します。これらの関数については以下で詳細に説明しますが、特徴としては、
anyに挿入またはanyから抽出される値のC++の型によって適切なTypeCodeが示されるという点です。
後述する型保障anyインタフェースはC++関数のオーバーロードに基づいているため、OMG IDL仕様から生成されるC++の型は別々のものである必要があります。ただし、この要件が満たされない特別な場合があります。
型保障の方法でanyの値を設定できるようにするために、OMG IDLの型Tごとに次のオーバーロード演算子関数が個別に用意されています。
•
|
Short, UShort, Long, ULong, Float, Double
|
•
|
operator<<=のコピー・バージョンの場合、Anyの値の存続期間は、 operator<<=に渡された値の存続期間に依存しません。Anyの実装では、 operator<<=に渡された値への参照またはポインタとして、その値を格納しません。
|
•
|
operator<<=の非コピー・バージョンの場合、挿入された T*はAnyが処理します。挿入後はAnyがT*の所有権を想定するため、呼出し側は指されたデータに T*を使用してアクセスできず、Anyは指されたデータを直ちにコピーして元のデータを破棄します。
|
•
|
operator<<=のコピーと非コピーの両バージョンでは、 Anyが保持していた前の値がすべて適切に割当て解除されます。たとえば、 「型付けされていない値の処理」で説明した Any(TypeCode_ptr,void*,TRUE)コンストラクタを呼び出して Anyを作成した場合、 Anyは void*が指すメモリーの割当てを解除してから、新しい値をコピーします。
|
Array_forany型は、
constへの参照によって常に
operator<<=に渡されます。
Array_foranyコンストラクタの
nocopyフラグは、挿入された値をコピーするか(
nocopy == FALSE)、処理するか(
nocopy == TRUE)を制御するために使用します。
nocopyフラグはデフォルトで
FALSEに指定されているため、デフォルトでは挿入がコピーされます。
Tの配列と
T*には型にあいまいさがあるため、移植性のあるコードの場合は、配列をAnyに挿入するときに適切な
Array_forany型を明示的に使用することをお薦めします。例:
オブジェクト参照のoperator<<=の非コピー・バージョンでは、次のように
T_ptr型のアドレスを取得します。
非コピーのオブジェクト参照の挿入では、T_ptr*が指すオブジェクト参照を処理します。したがって、Anyが元のオブジェクト参照を複製してすぐに解放するため、挿入後に呼出し側は、
T_ptrが参照するオブジェクトにアクセスできません。呼出し側は、
T_ptr自体のストレージの所有権を保持します。
operator<<=のコピー・バージョンは、
Any_var型でもサポートされます。
型保障の方法でanyから値を取得できるようにするために、ORBではOMG IDLの型Tごとに次の演算子が用意されています。
この場合、型Longのoperator>>=のバージョンは、Anyが型
Longの値を格納しているかどうかを判別します。格納している場合、呼出し側によって提供された参照変数にその値をコピーし、
TRUEを返します。Anyが型
Longの値を格納していない場合、呼出し側のリファレンス変数の値は変更されず、
operator>>=は
FALSEを返します。
抽出に成功した場合、呼出し側のポインタはAnyが管理するストレージを指し、operator>>=は
TRUEを返します。呼出し側は、このストレージの
deleteまたは解放を試行する必要はありません。また、代入、挿入、または
replace関数によってAny変数が置き換えられた後、またはAny変数が破棄された後に、呼出し側はストレージを使用する必要もありません。ただし、これらの抽出演算子で
T_var型を使用しないよう注意する必要があります。これは、Anyによって所有されるストレージを抽出演算子が削除しようとするためです。
Array_forany型は、参照によって常に
operator>>=に渡されます。
operator>>=は、
Any_var型でもサポートされます。
boolean、charおよびoctetがすべてC++型のunsigned charにマッピングされる場合、boolean、charまたはoctet型のanyの直接挿入または抽出を試行すると、
unsigned char用のプライベートで未実装の
operator<<=および
operator>>=関数によって、コンパイル・エラーが発生します。
to_objectヘルパー型は、Anyからオブジェクト参照を基本Object型として抽出するために使用します。AnyにそのTypeCodeとして示されたオブジェクト参照型の値がある場合、抽出関数
operator>>=(to_object)は、その格納されているオブジェクト参照を明示的にObject型に拡大し、
TRUEを返します。それ以外の場合は、FALSEを返します。抽出されたオブジェクト参照の型の拡大を実行するのは、オブジェクト参照抽出関数のみです。通常のオブジェクト参照の抽出と同じく、
to_object抽出演算子は、オブジェクト参照を複製しません。
コンストラクタは、指定されたTypeCode擬似オブジェクト参照を複製します。releaseパラメータが
TRUEの場合、Anyオブジェクトは
valueパラメータが指すストレージの所有権を想定します。
valueパラメータが
release=TRUEの指定でAnyに対して処理された後は、呼出し側はこのパラメータの存続期間を想定できません。これは、Anyが
valueパラメータをコピーして、直ちに元のポインタを解放するためです。
releaseパラメータがデフォルトの
FALSEの場合、Anyオブジェクトは、
valueによって指されるメモリーを呼出し側が管理すると想定します。
valueパラメータはNULLポインタでもかまいません。
replace関数は、型保障挿入インタフェースで使用不可能な型で使用します。したがって、この関数は前述のコンストラクタに似ています。既存のTypeCodeは解放され、必要に応じて値のストレージの割当てが解除されます。TypeCode
関数のパラメータは複製されます。
releaseパラメータが
TRUEの場合、Anyオブジェクトは、
valueパラメータが指すストレージの所有権を想定します。
valueパラメータが
release=TRUEの指定で
Any::replace関数に対して処理された後は、Anyはこのパラメータの存続期間を想定できません。これは、Anyが
valueパラメータをコピーして、直ちに元のポインタを解放するためです。
releaseパラメータがデフォルトの
FALSEの場合、Anyオブジェクトは、値が入っているメモリーを呼出し側が管理すると想定します。
replace関数の
valueパラメータはNULLポインタでもかまいません。
前述のコンストラクタもreplace関数も型保障ではありません。特に、TypeCodeと
void*引数の実際の型との一貫性については、実行時にコンパイラは保証しません。一致しないTypeCodeと値で
Anyが作成される場合の、ORB実装の動作は定義されません。
type関数は、Anyに関連付けられたTypeCodeに
TypeCode_ptr擬似オブジェクト参照を返します。すべてのオブジェクト参照の戻り値と同様に、リファレンスが不要になったときに呼出し側は、それを解放するか、または自動管理を行うために
TypeCode_var変数を割り当てる必要があります。
value関数は、Anyに格納されているデータへのポインタを返します。Anyに関連付けられている値がない場合、
value関数はNULLポインタを返します。
デフォルトのコンストラクタは、値を作成せずに、型tk_nullのTypeCodeでAnyを作成します。コピー・コンストラクタは、Anyパラメータの
TypeCode_ptrで
_duplicateを呼び出し、パラメータの値をディープ・コピーします。代入演算子は、それ自身の
TypeCode_ptrを解放し、必要に応じて現在の値のストレージを割当て解除します。その後、Anyパラメータの
TypeCode_ptrを複製し、パラメータの値をディープ・コピーします。デストラクタは、
TypeCode_ptrで
releaseを呼び出し、必要に応じて値のストレージを割当て解除します。
この項は、Object Management Group (OMG)の『Common Object Request Broker: Architecture and Specification, Revision 2.4.2』(2001年2月)の第3章、第5章、および第6章、および
『CORBA C++ Language Mapping Specification』(1999年6月)に記載されている情報に基づいています。OMGの許可を得て使用されています。
TYPE_varクラスのデフォルトのコンストラクタです。このコンストラクタは0(ゼロ)に初期化します。この値は、varクラスが
TYPE *を所有することを示します。有効な
TYPE *を割り当てていないかぎり、
TYPE_varクラスで
operator->を呼び出すことはできません。
このコンストラクタは、指定のTYPE *パラメータの所有権を想定します。
TYPE_varが破棄されると、
TYPEは解放されます。
Value引数は、このvarクラスが所有する
TYPEへのポインタです。このポインタは0(ゼロ)に指定しないでください。
このコピー・コンストラクタは、新しいTYPEを割り当てて、
Fromパラメータが所有する
TYPEに格納されているデータをディープ・コピーします。
TYPE_varが破棄されると、
TYPEのコピーは解放または削除されます。
Fromパラメータには、コピー元の
TYPEを指すvarクラスを指定します。
このデストラクタは、varクラスが所有するTYPEを適切なメカニズムで解放します。文字列の場合は、
CORBA::string_freeルーチンです。その他の参照の場合は、
CORBA::release ルーチンです。その他の型の場合は
delete、または割当て済メモリーを解放するために生成された静的ルーチンです。
この代入演算子は、NewValueパラメータが指すTYPEの所有権を想定します。現在、
TYPE_varが
TYPEを所有している場合、それを解放してから、
NewValueパラメータの所有権を想定します。
NewValue引数は、このvarクラスが所有する
TYPEへのポインタです。このポインタは0(ゼロ)に指定しないでください。
この代入演算子は、新しいTYPEを割り当てて、
From TYPE_varパラメータが所有する
TYPEに格納されているデータをディープ・コピーします。現在、
TYPE_varが
TYPEを所有している場合は解放されます。
TYPE_varが破棄されると、
TYPEのコピーは解放されます。
Fromパラメータには、コピー元のデータを指すvarクラスを指定します。
これらの演算子は、varクラスが所有しているTYPEへのポインタを返します。varクラスは、引き続き
TYPEを所有し、
TYPEを解放します。varが有効な
TYPEを所有していない場合は、
operator->を使用できません。
TYPE_varが破棄された後に、この戻り値の解放またはアクセスを試行しないでください。
暗黙的な変換を実行すると、一部のC++コンパイラやコードの可読性に問題が生じることがあります。そのため、TYPE_var型では、パラメータ渡しのために明示的な変換を実行できるようにするメンバー関数もサポートしています。
TYPE__varおよび
inパラメータを渡すには、
in()メンバー関数を、
inoutパラメータを渡す場合は
inout()メンバー関数を、
outパラメータを渡す場合は
out()メンバー関数をそれぞれ呼び出します。
TYPE__varから戻り値を取得するには、
_return()関数を呼び出します。各
TYPE_
var型について、これらの関数の戻り値の型はそれぞれ、
表13-7で示す
in、
inout、
out、および基底の型
TYPEの戻り値モードの型にそれぞれ一致します。
|
|
|
TYPE * operator-> () TYPE * operator-> () const
|
|
TYPE * operator-> () TYPE * operator-> () const
|
|
TYPE * operator-> () TYPE * operator-> () const TYPE & operator[](CORBA::Long index)
|
|
TYPE_slice & operator[](CORBA::Long index) TYPE_slice & operator[](CORBA::Long index) const
|
この演算子は、varクラスが所有するシーケンスのoperator[]を呼び出します。
operator[]は、指定の索引でシーケンスの適切な要素へのリファレンスを返します。
Index引数には、戻り値となる要素の索引を指定します。この索引は、現在のシーケンスの長さを超えることはできません。
この項と「シーケンスvar」という項で説明するメンバー関数の文字列varには、
char *の
TYPEがあります。文字列varでは、次のメンバー関数を追加でサポートします。
このコンストラクタは、文字列からString_varを作成します。
str引数には、想定される文字列を指定します。
strポインタを使用して、データにアクセスしないでください。
このコンストラクタは、const
文字列から
String_varを作成します。
str引数には、コピー元となるconst文字列を指定します。
var引数には、コピー元となる文字列へのリファレンスを指定します。
この代入演算子は、CORBA::string_freeを使用して格納されている文字列を解放してから、入力文字列の所有権を想定します。
str引数には、この
String_varオブジェクトが所有権を想定する文字列を指定します。
この代入演算子は、CORBA::string_freeを使用して格納されている文字列を解放してから、入力文字列をコピーします。
Data引数には、この
String_varオブジェクトが所有権を想定する文字列を指定します。
これらの配列演算子は、文字列内の文字へのアクセスを提供する上付きの演算子です。Index引数には、配列内の特定の文字にアクセスするときに使用する配列の索引を指定します。索引の基数はゼロです。
Char operator[] (Ulong Index)関数の戻り値は、lvalueとして使用できます。
Char operator[] (Ulong Index) const関数の戻り値は、lvalueとして使用できません。
|
|
|
TYPE * operator-> () TYPE * operator-> () const
|
|
TYPE * operator-> () TYPE * operator-> () const
|
|
TYPE * operator-> () TYPE * operator-> () const TYPE & operator[](CORBA::Long index)
|
|
TYPE_slice & operator[](CORBA::Long index) TYPE_slice & operator[](CORBA::Long index) const
|
TYPE_varを
outパラメータとして渡すと、参照先であった前の値はすべて暗黙的に削除する必要があります。の要件を満たす上で十分なフックをORBに付与するために、各
T_var型には対応する
TYPE_out型があります。この型は、
outパラメータ型としてのみ使用します。
注意:
|
プログラマは、_outクラスを直接インスタンス化できません。そのため、 _outクラスは関数のシグネチャでのみ指定してください。
|
可変長型のTYPE_out型の全般的な形式は、次のとおりです。
// assignment from TYPE_var not allowed
void operator=(const TYPE_var&):
};
最初のコンストラクタは、参照データ・メンバーをT*&引数にバインドし、ポインタをゼロ(0)ポインタ値に設定します。2番目のコンストラクタは、リファレンス・データ・メンバーを
TYPE_var引数が保持するポインタにバインドし、ポインタに対して
deleteを呼び出します(その際、型が
String_outの場合は
string_free()を、配列型
TYPEが
TYPE_varの場合は
TYPE_free()を呼び出します)。3番目のコンストラクタはコピー・コンストラクタで、コンストラクタ引数のデータ・メンバーによって参照される同じポインタにリファレンス・データ・メンバーをバインドします。
他のTYPE_outから代入すると、
TYPE_out引数によって参照される
TYPE*がデータ・メンバーにコピーされます。
TYPE*のオーバーロードの代入演算子は、ポインタ引数をデータ・メンバーに代入するだけです。この意味で、
TYPE_out型の動作は、
TYPE*とまったく同じです。
TYPE*&変換演算子は、データ・メンバーを返します。
ptr()メンバー関数もデータ・メンバーを返しますが、暗黙的な変換の実行を避ける場合に使用できます。オーバーロードの矢印演算子(
operator->())を使用すると、
TYPE*データ・メンバーが指すデータ構造体のメンバーにアクセスできます。準拠アプリケーションでは、有効な非NULL
TYPE*で
TYPE_outが初期化済ない限り、オーバーロードの
operator->()を呼び出すことはできません。
対応する_var型のインスタンスから、
TYPE_outに代入することはできません。これは、アプリケーション開発者がコピーを行うかどうか、または
TYPE_varが
TYPE_outに代入できるよう、それが管理するポインタの所有権を返すかどうかを判定する方法がないためです。
TYPE_varを
TYPE_outにコピーするには、アプリケーションで次のように
newを使用する必要があります。
// C++
TYPE_var t = ...;
my_out = new TYPE(t.in()); // heap-allocate a copy
通常、tに対して呼び出される
in()関数は、
const TYPE&を戻して、新しく割り当てられた
Tインスタンスのコピー・コンストラクタを呼び出すことができるようにします。
また、TYPE_varで、
T_outパラメータで返されるよう、それが管理するポインタの所有権を返すには、アプリケーションで、次のように
TYPE_var::_retn()関数を使用する必要があります。
// C++
TYPE_var t = ...;
my_out = t._retn(); // t yields ownership, no copy
TYPE_out型は、アプリケーションで作成または破棄される汎用目的のデータ型としては機能しません。この型は必要なメモリー管理を適切に行う目的で、操作のシグネチャの内部でのみ使用する型です。
__varを
outパラメータとして渡すと、参照先の前の値はすべて暗黙的に解放する必要があります。この要件を満たす上でC++マッピング実装に十分なフックを付与するために、オブジェクト参照型ごとに
_out型が生成されます。この型は、
outパラメータ型としてのみ使用します。たとえば、インタフェース
TYPEの場合、オブジェクト参照型
TYPE_ptr、ヘルパー型
TYPE_var、および
outパラメータ型
TYPE_outが生成されます。オブジェクト参照
_out型の全般的な形式は次のとおりです。
// C++
class TYPE_out
{
public:
TYPE_out(TYPE_ptr& p) : ptr_(p) { ptr_ = TYPE::_nil(); }
TYPE_out(TYPE_var& p) : ptr_(p.ptr_) {
release(ptr_); ptr_ = TYPE::_nil();
}
TYPE_out(TYPE_out& a) : ptr_(a.ptr_) {}
TYPE_out& operator=(TYPE_out& a) {
ptr_ = a.ptr_; return *this;
}
TYPE_out& operator=(const TYPE_var& a) {
ptr_ = TYPE::_duplicate(TYPE_ptr(a)); return *this;
}
TYPE_out& operator=(TYPE_ptr p) { ptr_ = p; return *this; }
operator TYPE_ptr&() { return ptr_; }
TYPE_ptr& ptr() { return ptr_; }
TYPE_ptr operator->() { return ptr_; }
private:
TYPE_ptr& ptr_;
};
この演算子は、outクラスが所有するシーケンスのoperator[]を呼び出します。
operator[]は、指定の索引でシーケンスの適切な要素へのリファレンスを返します。
Index引数には、戻り値となる要素の索引を指定します。この索引は、現在のシーケンスの長さを超えることはできません。
String_varを
outパラメータとして渡すと、参照先の前の値はすべて暗黙的に解放する必要があります。この要件を満たす上でC++マッピング実装に十分なフックを付与するために、文字列型にもCORBAネームスペースで
String_out型が生成されます。この型は、文字列
outパラメータ型としてのみ使用します。
String_out型の全般的な形式は次のとおりです。
最初のコンストラクタは、参照データ・メンバーをchar*&引数にバインドします。2番目のコンストラクタは、リファレンス・データ・メンバーを
String_var引数が保持する
char*にバインドし、文字列に対して
string_free()を呼び出します。3番目のコンストラクタはコピー・コンストラクタで、その引数のデータ・メンバーにバインドされる同じ
char*に、リファレンス・データ・メンバーをバインドします。
他のString_outから代入すると、
String_out引数によって参照される
char*が、データ・メンバーによって参照される
char*にコピーされます。
char*のオーバーロードの代入演算子は、
char*引数をデータ・メンバーに代入するだけです。
const char*のオーバーロードの代入演算子は、引数を複製して結果をデータ・メンバーに代入します。代入を行っても、以前に保持されていた文字列はまったく削除されません。この意味で、
String_out型の動作は、
char*とまったく同じです。
char*&変換演算子は、データ・メンバーを返します。
ptr()メンバー関数もデータ・メンバーを返しますが、暗黙的な変換の実行を避ける場合に使用できます。
String_varから
String_outへの代入はできません。これは、メモリー管理にあいまいさが生じるためです。特に、
String_varによって所有される文字列を
String_outが取得するときに、コピーが行われるか、コピーなしで行われるかどうかを判別することは不可能です。
String_varからの代入が不可能なため、アプリケーション開発者は次のように明示的に指定しなければなりません。
コメントで「1」とマークされた行の場合、呼出し側はString_varが所有する文字列を明示的にコピーし、結果を
out引数に代入しています。また、呼出し側は、コメントで「2」とマークされた行で示すように、
String_varに文字列の所有権を強制的に放棄させるというテクニックも使用できます。これにより、メモリー管理のエラーを発生させずに
out引数に文字列を返すことができます。
outパラメータと
inoutパラメータのマッピングでは、
T_varが渡されるときにパラメータ内の以前の可変長データをすべて割当て解除する必要があります。これらのパラメータの初期値が操作に送信されない場合でも、Oracle Tuxedoには、
outパラメータがあります。これは、パラメータに以前の呼出しの結果が格納されている可能性があるためです。
T_out型が提供される目的は、
T_var型からの変換時にアクセスできないストレージを解放するのに必要なフックを実装に付与することです。次に、この動作の例を示します。
outパラメータと
inoutパラメータの前の値を暗黙的に割当て解除できるのは、
T_var型のみです。
ループ内でq関数を呼び出すたびに、メモリー・リークが発生します。これは、呼出し側が
out結果で
string_freeを呼び出していないことが原因です。これを修正するには、次に示す2つの方法があります。
outパラメータに通常の
char*を使用する場合、呼出し側は変数を毎回
outパラメータとして再利用する前に、明示的にメモリーを割当て解除する必要があります。一方、
String_varを使用した場合は、変数を
outパラメータとして使用するたびに、割当てがすべて暗黙的に解除されます。
可変長データは、上書きする前に、明示的に解放する必要があります。たとえば、inout文字列パラメータに代入する場合、操作の実装者はまず古い文字データを削除します。同様に、
inoutインタフェース・パラメータは、再割り当てされる前に解放する必要があります。パラメータのストレージを確実に解放する方法としては、次の例に示すように、ストレージをローカル
T_var変数に割り当てて自動的に解放が行われるようにすることです。
パラメータがポインタ(T*)またはポインタ(
T*&)への参照として受け渡しされる場合、アプリケーションはNULLポインタを受渡しできません。これを実行すると、結果は未定義になります。特に、次のどちらかに該当する場合、呼出し側はNULLポインタを渡すことができません。
•
|
inおよび inout配列(最初の要素へのポインタ)
|
ただし、呼出し側は、outパラメータのNULL値でポインタへの参照を渡すことはできます。これは、呼出し先が値を確認せずに上書きするためです。呼出し先は、次のいずれかに該当する場合、NULLポインタを渡すことができません。
表13-7には、受け渡しされる型に応じた、基本OMG IDLパラメータ渡しモードおよび戻り値の型のマッピングを示します。
表13-8には、
T_var型の場合の同様の情報を示します。
表13-8は、あくまで参考用に提供されています。これは、
T_out型がすべての
outパラメータの実際のパラメータ型として使用される点を除けば、クライアントとサーバーの操作のシグネチャが、
表13-7で示すパラメータ渡しモードでコーディングされるためです。
また、T_var型では、この型を直接渡すために必要な変換演算子をサポートします。呼出し側は、
T_var型または
表13-7で示すベース・タイプのインスタンスを常に渡す必要があります。呼出し先は、その
T_outパラメータが実際に
表13-7の対応する、基底の型であるように扱う必要があります。
表13-7の中で、固定長の配列が適用対象となるのは、
outパラメータの型が戻り値と異なる場合のみです。
これが必要となるのは、C++では関数で配列を返すことができないためです。マッピングは、配列のスライス
へのポインタを返します。
配列のスライスとは、指定された元の配列の最初のサイズを除いたすべてのサイズを持つ配列のことです。
呼出し側は、in引数として渡される引数すべてにストレージを提供する必要があります。
表13-9および
表13-10では、
inoutパラメータと
outパラメータに関連付けられたストレージ、および戻り値の結果に対する呼出し側の作業について説明します。
|
|
|
呼出し側は必要なストレージをすべて割り当てます。ただし、パラメータ自体の中でカプセル化および管理できるストレージは除きます。inoutパラメータの場合、呼出し側は初期値を指定し、呼出し先はその値を変更できます。 outパラメータの場合、呼出し側はストレージを割り当てますが初期化する必要はなく、呼出し先が値を設定します。関数は値で戻り値を返します。
|
|
呼出し側は、オブジェクト参照のストレージを割り当てます。inoutパラメータの場合、呼出し側は初期値を指定します。呼出し先が inoutパラメータを再割当てする場合は、まず、元の入力値で CORBA::releaseを呼び出します。 inoutとして渡されたオブジェクト参照を引き続き使用するには、呼出し側は最初にリファレンスを複製する必要があります。そして、 outをすべて解放してから、オブジェクト参照を返します。ほかの構造体に埋め込まれたオブジェクト参照はすべて、各構造体自体によって自動的に解放されます。
|
|
outパラメータの場合、呼出し側はポインタを割り当て、それを呼出し先に参照で渡します。呼出し先は、パラメータの 型の有効なインスタンスを指すようにポインタを設定します。戻り値の場合は、呼出し先は同様のポインタを返します。どちらの場合でも、呼出し先はNULLポインタを返すことはできません。
|
|
inout文字列の場合、呼出し側は、入力文字列とそれを指す char*の両方にストレージを割り当てます。呼出し先が入力文字列の割当てを解除し、新しいストレージを指す char*を再割り当てして出力値を保持する可能性があるため、呼出し側は string_alloc()を使用して入力文字列を割り当てる必要があります。そのため、 out文字列のサイズはin文字列のサイズに制限されません。呼出し側は、 string_free()を使用して outのストレージを削除する必要があります。呼出し先は、 inout、 out、または戻り値に対してNULLポインタを返すことはできません。
|
|
inoutシーケンスおよび anyの場合、シーケンスまたは anyを作成したBoolean解放パラメータの状態によっては、シーケンスまたは anyを割り当てまたは変更することにより、再割当てが行われる前に、所有しているストレージの割当てが解除される場合があります。
|
|
outパラメータの場合、呼出し側は配列スライス(元の配列の最初のサイズを除いたすべてのサイズを持つ配列)へのポインタを割り当て、参照でポインタを呼出し先に渡します。呼出し先は、配列の有効なインスタンスを指すようにポインタを設定します。
|