この問題の一般的な解決策は、関数ポインターのテーブルを宣言し、それを見つけるために単一のdlsym()を実行してから、そのテーブルへのポインターを介して他のすべての関数を呼び出すことです。例(未テスト):
// libfoo.h
struct APIs {
void (*api1)(void);
void *(*api2)(int);
long (*api3)(int, void *);
};
// libfoo.cc
void fn1(void) { ... }
void *fn2(int) { ... }
long fn3(int, void *) { ... }
APIs api_table = { fn1, fn2, fn3 };
// client.cc
#include "libfoo.h"
...
void *foo_handle = dlopen("libfoo.so", RTLD_LAZY);
if (!foo_handle) {
return false; // library not present
}
APIs *table = dlsym(foo_handle, "api_table");
table->api1(); // calls fn1
void *p = table->api2(42); // calls fn2
long x = table->api3(1, p); // calls fn3
PS dlsymとポインタを使用してAPI関数に個別にアクセスしても、それ自体ではメモリの破損やクラッシュは発生しません。ほとんどの場合、バグがあります。
編集:
サードパーティのライブラリでこれとまったく同じ手法を使用できます。を作成し、libdrmaa_wrapper.so
それに入れますapi_table
。ラッパーをに直接リンクしますlibdrmaa.so
。
メインの実行可能ファイルでは、dlopen("libdrmaa_wrapper.so", RTLD_NOW)
。これは、実行時に存在し、で使用したすべてのAPI関数を提供するdlopen
場合にのみ成功します。成功した場合は、1回の呼び出しでAPI全体にアクセスできます。libdrmaa.so
api_table
dlsym