ノード:Module loaders for libltdl, 次:, 前:User defined module data, 上:Using libltdl



新しいモジュールローダの作成方法と登録方法

モジュールにアクセスするためのlibltdlの方法は多いけれど,プロジェクト の目的に十分でないときもあります.独自のローダを書き,lt_dlopen が利用できるように,libltdlでそれを登録することが可能です.

ローダを書くことは,lt_dlopenlt_dlsymそして lt_dlcloseで呼び出し可能な,少なくとも三つの関数を書くことを必 要とします.オプションで,lt_dlexitが実行されるときクリーンアッ プ処理を実行する終了関数と,lt_dlsymに渡されるあらゆるシンボル に前置されるシンボルの前置文字を提供することも可能です.これらの関数は, 以下の関数のポインタ型に一致する必要があり,その後,それらを lt_user_dlloaderの代わりに関連付けし,登録することが可能です.

ローダの登録には,lt_dlloader_findが認識でき, lt_dlloader_removeで削除できるように,それに対する名前を選択す ることが必要です.選択した名前はユニークである必要があり,libltdlの組 み込みローダで既に使用しているものはいけません.

"dlopen"
存在する場合は,システムのダイナミックローダ.
"dld"
libltdlがビルドされたときにlibdldがインストールされている場合は, GNU dldローダ.
"dlpreload"
プリロードされているスタティックモジュールのlt_dlopenのためのロー ダ.

前置される"dl"は,libltdlの将来のバージョンで提供されるローダとして予 約されているので,独自のローダ名に使用すべきではありません.

以下の型は,ltdl.hで定義されています.

lt_module Type
lt_moduleはモジュール依存のdlloaderです.ダイナミックモジュール ローダの拡張は,これらの低レベルの型を使用して通信を行ないます.

lt_dlloader Type
lt_dlloaderはモジュールローダの型に対するハンドルです.

lt_user_data Type
lt_user_dataはローダのインスタンスデータに対して使用されます.

struct lt_user_dlloader {const char *sym_prefix; lt_module_open *module_open; lt_module_close *module_close; lt_find_sym *find_sym; lt_dlloader_exit *dlloader_exit; } Type
ダイナミックモジュールを開くために新しい方法を定義したくて,それを使用 したlt_dlopen APIがある場合,これらの構造体のインスタンス を作成し,それをlt_dlloader_addに渡す必要があります.好みの dlloader_dataフィールドで渡すことが可能で,それは,関数ポインタ フィールドで指定されている,それぞれの関数への最初のパラメータの値とし て返されます.

lt_module lt_module_open (const char *filename) Type
lt_dlloaderモジュールローダに対するローダ関数の型です. struct lt_user_dlloader構造体のdlloader_dataフィールドに設定さ れる値は,loader_dataパラメータで,この関数に渡されます.そのよ うな関数の実装は,指名されたモジュールのロードを試み,関連する lt_module_closelt_sym_find関数のポインタに渡すのに適切 なlt_moduleを返すべきです.関数が失敗した場合はNULLを返 し,lt_dlseterrorを用いてエラーメッセージを設定すべきです.

int lt_module_close (lt_user_data loader_data, lt_module module) Type
ユーザが定義したモジュールローダに対するアンローダの型です.そのような 関数の実装は,moduleモジュールに結び付けられたあらゆるリソースの 解放を試み,その後でメモリからアンロードすべきです.理由があって関数が 失敗した場合,lt_dlseterrorを用いてエラーメッセージを設定し,ゼ ロ以外を返すべきです.

lt_ptr lt_find_sym (lt_module module, const char *symbol) Type
ユーザが定義したモジュールローダに対する,シンボルルックアップ関数の型 です.そのような関数の実装は,モジュールmodule内の指名された symbolのアドレスを返す,もしくは,検査が失敗した場合は,エラーメッ セージをlt_dlseterrorで設定し,NULLを返すべきです.

int lt_dlloader_exit (lt_user_data loader_data) Type
ユーザが定義したモジュールローダに対する,終了関数の型です.そのような 関数の実装は,ローダに関連するあらゆるリソースを解放すべきで,それには lt_user_dlloaderdlloader_dataフィールド内部にあるユー ザが指定したあらゆるデータを含みます.NULLでない場合は,関数は lt_dlexitlt_dlloader_removeから呼び出されます.

例えば,以下のようにします.

     int
     register_myloader (void)
     {
       lt_user_dlloader dlloader;
     
       /* User modules are responsible for their own initialisation. */
       if (myloader_init () != 0)
         return MYLOADER_INIT_ERROR;
     
       dlloader.sym_prefix    = NULL;
       dlloader.module_open   = myloader_open;
       dlloader.module_close  = myloader_close;
       dlloader.find_sym      = myloader_find_sym.
       dlloader.dlloader_exit = myloader_exit;
       dlloader.dlloader_data = (lt_user_data)myloader_function;
     
       /* Add my loader as the default module loader. */
       if (lt_dlloader_add (lt_dlloader_next (NULL), &dlloader, "myloader") != 0)
         return ERROR;
     
       return OK;
     }
     

ローダに対する必要な初期化がある場合は,ローダが登録される前に手動で実 行する必要があることに注意してください - libltdlはユーザローダの初期 化を扱いません.

終了はlibltdlで扱われますが,dlloader_exitのコールバック が初期化フェーズの間に要求された,あらゆるリソースを解放することを確か めることは重要です.

libltdlは,独自のモジュールローダを書くために,以下の関数を提供します.

int lt_dlloader_add (lt_dlloader *place, lt_user_dlloader *dlloader, const char *loader_name) 機能
新しいモジュールローダを全てのローダリストに加え,それは,(placeNULLの場合は)最後のローダとして,それ以外ではplaceとし て渡されたローダの直前に加えます.loader_nameは,新しく登録され たローダが渡された場合,lt_dlloader_nameを返します,これらの loader_nameは,ユニークである必要があり,そうでない場合は, lt_dlloader_removelt_dlloader_findは動作不可能です.成 功に対し0を返します.
          {
            /* Make myloader be the last one. */
            if (lt_dlloader_add (NULL, myloader) != 0)
              perror (lt_dlerror ());
          }
          

int lt_dlloader_remove (const char *loader_name) 機能
ユニークな名前loader_nameで識別されているローダを削除します.こ れが成功可能となる前に,指名されたローダにより開かれている全てのモジュー ルを,閉じておく必要があります.成功に対し0を返し,それ以外では,エラー メッセージがlt_dlerrorから取得可能です.
          {
            /* Remove myloader. */
            if (lt_dlloader_remove ("myloader") != 0)
              perror (lt_dlerror ());
          }
          

lt_dlloader * lt_dlloader_next (lt_dlloader *place) 機能
ローダモジュール全体を繰り返し,それは,placeNULLの場合 は最初のローダを返し,順番に次を呼び出すことで行います.ハンドルは, lt_dlloader_add用です.
          {
            /* Make myloader be the first one. */
            if (lt_dlloader_add (lt_dlloader_next (NULL), myloader) != 0)
              return ERROR;
          }
          

lt_dlloader * lt_dlloader_find (const char *loader_name) 機能
loader_name識別子に一致する最初のローダを返し,識別子が見つから ない場合はNULLを返します.

libltdl自身で使用可能な識別子は,ホストアーキテクチャがサポートしてい る場合はdlopen1dld,そしてdlpreloadです.

          {
            /* Add a user loader as the next module loader to be tried if
               the standard dlopen loader were to fail when lt_dlopening. */
            if (lt_dlloader_add (lt_dlloader_find ("dlopen"), myloader) != 0)
              return ERROR;
          }
          

const char * lt_dlloader_name (lt_dlloader *place) 機能
lt_dlloader_nextlt_dlloader_findで取得される, PLACEの識別名を返します.この関数が失敗する場合,NULLを返 し,lt_dlerrorで回収するためのエラーを設定します.

lt_user_data * lt_dlloader_data (lt_dlloader *place) 機能
lt_dlloader_nextlt_dlloader_findで取得される, PLACEのアドレスを返します.この関数が失敗する場合,NULLを 返し,lt_dlerrorで回収するためのエラーを設定します.

ユーザモジュールローダでのエラー処理

int lt_dladderror (const char *diagnostic) 機能
この関数で,独自のエラーメッセージをlt_dlerrorに組み込むことが 可能となります.lt_dlerrorで返すための適切な診断メッセージに渡 すものと,lt_dlseterrorで使用されるエラー識別子が返されます.

識別子の割り当てが失敗した場合,この関数は-1を返します.

          int myerror = lt_dladderror ("Doh!");
          if (myerror < 0)
            perror (lt_dlerror ());
          

int lt_dlseterror (int errorcode) 機能
独自のモジュールローダを書くとき,lt_dlerrorインターフェースを 通じて伝搬されるようにエラーを発生させるために,この関数を使用すべきで す.libltdlで使用される標準エラーの全ては,ltdl.hで宣言されてい て,そうでなければ,lt_dladderrorを用いて独自に書き加えることが 可能です.
          if (lt_dlseterror (LTDL_ERROR_NO_MEMORY) != 0)
            perror (lt_dlerror ());
          


脚注

  1. これは,モジュールをロードしている API に依存します -- 例えば,shl_loadLoadLibraryで す