モジュールにアクセスするための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_dlopenapiがある場合,これらの構造体のインスタンス を作成し,それを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 ());