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

4.5.7 共用体

(1)IDLマッピング

IDL言語で共用体unionを指定した場合、C++言語ではデータ型を識別する弁別情報_dと共用体データ域_ptrから構成される共用体クラスにマッピングされます。
以降では、以下のIDL定義例をもとに説明します。


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

C++言語
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)関数は、パラメタで指定した値を弁別子に設定します。
_d()は、弁別子を返します。

メンバアクセス関数

“メンバ名(変数)”の形式で呼び出すことによりメンバの値をデータ格納域に設定します。メモリ不足によりデータ格納域の獲得に失敗した場合は、_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に設定されているデータが複写されます。