動的参照シンボル [Sym]

目次


1. ● Sym の概要

文字列で構造体のシンボルを指定して構造体の中のデータを参照したり 関数を呼び出したりできるようにします。


2. ● SYM_STRUCT マクロの説明

2-1. SYM_STRUCT マクロ

Sym が動的に構造体の内容を参照できるようにするに、 構造体の構成を登録しておく必要があります。 登録するには、SYM_STRUCT 系マクロを使用して 関数(〜_registSymStruct)を定義し、その関数を 呼び出します。

ヘッダファイル中に、以下のようなプロトタイプ宣言をします。
extern  Sym_Struct*   Struct_registSymStruct( Sym* );  // (構造体型名) + _registSymStruct
extern  Sym_Struct    Struct_symStruct;                // (構造体型名) + _symStruct
〜_registSymStruct 関数の返り値は、登録した動的参照構造体です。

ソースファイル中に次のように記述すると Struct_registSym (構造体型名+_registSymStruct)関数を定義します。
SYM_STRUCT_START( Struct )
SYM_STRUCT_LOOP_FUNC( Struct, Struct_doLoopFunc )
SYM_STRUCT_MEMB_FUNC( Struct, Struct_doReadMemb, NULL )
SYM_STRUCT_MEMB( Struct, int, name )
SYM_STRUCT_MEMB( Struct, void*, adr )
SYM_STRUCT_ST( Struct, Sub, sub )
SYM_STRUCT_STP( Struct, Sub, sub_p )             // Sub* 型
SYM_STRUCT_STP_ST( Struct, ListX, Sub, sub_p )   // ListX* 集合 Sub 型要素
SYM_STRUCT_END( Struct )
その他の SYM_STRUCT 系マクロは、ヘッダファイルの SYM_STRUCT... マクロを 参照してください。

初期化関数で、動的参照構造体を登録するとよいでしょう。
void  Struct_init( Struct* this )
{
  static  int  bStart = 1;
  if ( bStart )  { Struct_registSymStruct( &sym );  bStart = 0; }
  Sym_registVar( &sym, "Struct", "take", this );
}

後始末関数で、動的参照構造体の登録を解除するとよいでしょう。
void  Struct_finish( Struct* this )
{
  Sym_unregistVar( &sym, "take" );
}

2-2. 集合走査関数

集合を走査する関数(Sym_LoopF 型)は、 集合を扱うコンテナクラスに対して SYM_STRUCT_LOOP_FUNC マクロに指定し、 次のように内容を記述します。
/************************************************************************
*  <<< [ListX_doLoopFunc] SYM_STRUCT_LOOP_FUNC に指定する関数 >>>
*【引数】
*  ・Sym_Ref*  container;   集合クラスの参照、または配列の先頭アドレス
*  ・Sym_Ref*  elem;        ループ変数(要素の参照)(入出力)
*  ・bool  返り値;          次の要素があったかどうか
************************************************************************/
#ifdef  USES_SYM
bool  ListX_doLoopFunc( Sym_Ref* container, Sym_Ref* elem )
{
  ListX*  this;

  if ( container->type == Sym_StructType )  this = container->adr;
  else  this = *(ListX**)container->adr;

  if ( elem->adr == NULL )  elem->adr = this->first;
  else   elem->adr = Offset_ref( (Offset)container->elem_param, elem->adr, void* );

  return  elem->adr != NULL;
}
#endif

2-3. 動的メンバ変数値取得/設定関数

SYM_STRUCT マクロを使って静的に定義される構造体のメンバ変数を 取得できますが、動的にメンバ変数が変化する場合は、 Sym_ReadMembF 型の関数を SYM_STRUCT_MEMB_FUNC マクロに指定し、 次のように記述します。
/************************************************************************
*  <<< [Xxx_doReadMemb] SYM_STRUCT_MEMB_FUNC に指定する関数 >>>
*【引数】
*  ・Sym_Ref*  obj;    構造体の参照
*  ・char*     name;   メンバ変数名(変更不可)
*  ・Sym_Ref*  ret;    メンバ変数(出力)
************************************************************************/
#ifdef  USES_SYM
void  Xxx_doReadMemb( Sym_Ref* obj, char* name, Sym_Ref* ret )
{
  Xxx* this = obj->adr;

  if ( strcmp( name, "memb" ) == 0 ) {
    ret->adr = "memb";
    ret->type = Sym_CharP;
  }
}
#endif

メンバ変数設定関数(Sym_WriteMembF 型) の詳細は決まっていません(使えません)。

2-4. プロパティ・取得/設定関数

プロパティを参照する関数(Sym_ReadPropF 型)は SYM_STRUCT_PROP_MEMB マクロまたは SYM_STRUCT_PROP_STP マクロに指定し、 次のように内容を記述します。
void  Sym_Struct_getNextProp( void* obj, void* ret )
{
  Sym_Struct*  this = obj;        // オブジェクトの型にキャスト
  *(char**)ret = this->name + 1;  // プロパティの型へのポインタ型にキャストして格納
}

Sym_WritePropF 型の詳細は決まっていません (使えません)。


3. ● SYM_FUNC マクロの説明

ヘッダファイル中に、以下のようなプロトタイプ宣言をします。
Sym_Func*  symbol_registSymFunc( Sym* );   // (シンボル名) + _registSymFunc
返り値は、登録した動的参照関数です。

ソースファイル中に次のように記述すると atoi_registSymFunc 関数 (シンボル名+_registSymFunc)を定義します。
SYM_FUNC_START_R1( atoi, int, atoi, String )
SYM_FUNC_STRUCT_ARG( atoi, 1, String )
SYM_FUNC_END( atoi )
その他の SYM_FUNC 系マクロは、ヘッダファイルの SYM_FUNC... マクロを 参照してください。


4. ● Sym の処理概要

登録されたデータは、Sym_getRef 関数で取得します。
Sym_getRef 関数の内部では、Sym_getVar 関数で構造体のトップを 取得し、Sym_Ref_getRef 関数でメンバ変数を Sym_Ref 型で取得します。


written by M.Toda from May.8.2000