Next: Distributing libltdl, Previous: User defined module data, Up: Using libltdl
モジュールにアクセスするためのlibltdlの方法は多いけれど,プロジェクト
の目的に十分でないときもあります.独自のローダを書き,lt_dlopen
が利用できるように,libltdlでそれを登録することが可能です.
ローダを書くことは,lt_dlopen
,lt_dlsym
そして
lt_dlclose
で呼び出し可能な,少なくとも三つの関数を書くことを必
要とします.オプションで,lt_dlexit
が実行されるときクリーンアッ
プ処理を実行する終了関数と,lt_dlsym
に渡されるあらゆるシンボル
に前置されるシンボルの前置文字を提供することも可能です.これらの関数は,
以下の関数のポインタ型に一致する必要があり,その後,それらを
lt_user_dlloader
の代わりに関連付けし,登録することが可能です.
ローダの登録には,lt_dlloader_find
が認識でき,
lt_dlloader_remove
で削除できるように,それに対する名前を選択す
ることが必要です.選択した名前はユニークである必要があり,libltdlの組
み込みローダで既に使用しているものはいけません.
lt_dlopen
のためのロー
ダ.
前置される"dl"は,libltdlの将来のバージョンで提供されるローダとして予 約されているので,独自のローダ名に使用すべきではありません.
以下の型は,ltdl.hで定義されています.
ダイナミックモジュールを開くために新しい方法を定義したくて,それを使用 した
lt_dlopen
apiがある場合,これらの構造体のインスタンス を作成し,それをlt_dlloader_add
に渡す必要があります.好みの dlloader_dataフィールドで渡すことが可能で,それは,関数ポインタ フィールドで指定されている,それぞれの関数への最初のパラメータの値とし て返されます.
lt_dlloader
モジュールローダに対するローダ関数の型です.struct lt_user_dlloader
構造体のdlloader_dataフィールドに設定さ れる値は,loader_dataパラメータで,この関数に渡されます.そのよ うな関数の実装は,指名されたモジュールのロードを試み,関連するlt_module_close
とlt_sym_find
関数のポインタに渡すのに適切 なlt_module
を返すべきです.関数が失敗した場合はNULL
を返 し,lt_dlseterror
を用いてエラーメッセージを設定すべきです.
ユーザが定義したモジュールローダに対するアンローダの型です.そのような 関数の実装は,moduleモジュールに結び付けられたあらゆるリソースの 解放を試み,その後でメモリからアンロードすべきです.理由があって関数が 失敗した場合,
lt_dlseterror
を用いてエラーメッセージを設定し,ゼ ロ以外を返すべきです.
ユーザが定義したモジュールローダに対する,シンボルルックアップ関数の型 です.そのような関数の実装は,モジュールmodule内の指名された symbolのアドレスを返す,もしくは,検査が失敗した場合は,エラーメッ セージを
lt_dlseterror
で設定し,NULL
を返すべきです.
ユーザが定義したモジュールローダに対する,終了関数の型です.そのような 関数の実装は,ローダに関連するあらゆるリソースを解放すべきで,それには
lt_user_dlloader
のdlloader_data
フィールド内部にあるユー ザが指定したあらゆるデータを含みます.NULL
でない場合は,関数はlt_dlexit
とlt_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は,独自のモジュールローダを書くために,以下の関数を提供します.
新しいモジュールローダを全てのローダリストに加え,それは,(place が
NULL
の場合は)最後のローダとして,それ以外ではplaceとし て渡されたローダの直前に加えます.loader_nameは,新しく登録され たローダが渡された場合,lt_dlloader_name
を返します,これらの loader_nameは,ユニークである必要があり,そうでない場合は,lt_dlloader_remove
とlt_dlloader_find
は動作不可能です.成 功に対し0を返します.{ /* Make myloader be the last one. */ if (lt_dlloader_add (NULL, myloader) != 0) perror (lt_dlerror ()); }
ユニークな名前loader_nameで識別されているローダを削除します.こ れが成功可能となる前に,指名されたローダにより開かれている全てのモジュー ルを,閉じておく必要があります.成功に対し0を返し,それ以外では,エラー メッセージが
lt_dlerror
から取得可能です.{ /* Remove myloader. */ if (lt_dlloader_remove ("myloader") != 0) perror (lt_dlerror ()); }
ローダモジュール全体を繰り返し,それは,placeが
NULL
の場合 は最初のローダを返し,順番に次を呼び出すことで行います.ハンドルは,lt_dlloader_add
用です.{ /* Make myloader be the first one. */ if (lt_dlloader_add (lt_dlloader_next (NULL), myloader) != 0) return ERROR; }
loader_name識別子に一致する最初のローダを返し,識別子が見つから ない場合は
NULL
を返します.libltdl自身で使用可能な識別子は,ホストアーキテクチャがサポートしてい る場合はdlopen1,dld,そして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; }
lt_dlloader_next
やlt_dlloader_find
で取得される, PLACEの識別名を返します.この関数が失敗する場合,NULL
を返 し,lt_dlerror
で回収するためのエラーを設定します.
lt_dlloader_next
やlt_dlloader_find
で取得される, PLACEのアドレスを返します.この関数が失敗する場合,NULL
を 返し,lt_dlerror
で回収するためのエラーを設定します.
この関数で,独自のエラーメッセージを
lt_dlerror
に組み込むことが 可能となります.lt_dlerror
で返すための適切な診断メッセージに渡 すものと,lt_dlseterror
で使用されるエラー識別子が返されます.識別子の割り当てが失敗した場合,この関数は-1を返します.
int myerror = lt_dladderror ("Doh!"); if (myerror < 0) perror (lt_dlerror ());