ページの先頭行へ戻る
Interstage Application Server アプリケーション作成ガイド(CORBAサービス編)
Interstage

4.6.4 any型

(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 );  // リリースフラグ

IDL言語
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定義例をもとに、クライアント/サーバアプリケーションの記述例を示します。

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.6.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が設定されます。
なお、メモリ不足によりデータ域用の領域獲得に失敗した場合、_valueはNULLに設定されます。

コンストラクタ

(型定義されていない値用)

インスタンス生成時、パラメタで指定された値を_tcと_valueに設定します。リリースフラグは、指定された値が設定されます。リリースフラグの指定を省略した場合は、CORBA_FALSEが設定されます。

デストラクタ

リリースフラグがCORBA_TRUEの場合、_tcと_valueの値に対する領域を解放します。

代入演算子

リリースフラグがCORBA_TRUEの場合、現在設定されている_tcと_valueの値に対する領域を解放します。その後、データ域用の領域を獲得し、パラメタで指定された値を設定します。リリースフラグには、CORBA_TRUEが設定されます。
なお、メモリ不足によりデータ域用の領域獲得に失敗した場合、_valueにNULLが設定されます。

左シフト代入演算子

リリースフラグがCORBA_TRUEの場合、現在設定されている_tcと_valueの値に対する領域を解放します。その後、データ域用の領域を獲得し、パラメタで指定された値を設定します。リリースフラグには、CORBA_TRUEが設定されます。
なお、メモリ不足によりデータ域用の領域獲得に失敗した場合、_valueにNULLが設定されます。

右シフト代入演算子

_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を確認する必要があります。


helper関数

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関数

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; 
}

type関数

type関数は、Anyに関連づけられたCORBA::TypeCodeオブジェクトのオブジェクトリファレンスCORBA::TypeCode_ptrを返します。

CORBA::Any *a = new CORBA::Any();
CORBA::Long x; 
(*a) <<= x; 
    ... 
CORBA::TypeCode_ptr tc = a->type(); // _tcを取り出します。
if( tc->kind() == tk_long ){ 
       ...              // このプログラムでは、等しいためここが処理されます。
}

value関数

value関数は、Any型変数に設定されている_valueをvoid*型で返します。_valueに値が設定されていなければ、NULLポインタを返します。

CORBA::Any any; 
CORBA::Long x; 
x = 3; 
any <<= x;     // 左シフト代入演算子で_tcに_tc_longを_valueに値3を代入

CORBA::Long *p = (CORBA::Long *)any.value();
               // _valueを取り出します。void*型なのでCORBA::Long *型にキャスト

count << "(*p)=" << *p << endl;