13

関数を介して共有ライブラリがロードされたときdlopen()に、メインプログラムで関数を呼び出す方法はありますか?

4

3 に答える 3

24

dlo.c (ライブラリ) のコード:

#include <stdio.h>

// function is defined in main program
void callb(void);

void test(void) {
    printf("here, in lib\n");
    callb();
}

でコンパイル

gcc -shared -olibdlo.so dlo.c

メインプログラムのコード (dlopen マンページからコピーして調整):

#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>

void callb(void) {
    printf("here, i'm back\n");
}

int
main(int argc, char **argv)
{
    void *handle;
    void (*test)(void);
    char *error;

    handle = dlopen("libdlo.so", RTLD_LAZY);
    if (!handle) {
        fprintf(stderr, "%s\n", dlerror());
        exit(EXIT_FAILURE);
    }

    dlerror();    /* Clear any existing error */

    *(void **) (&test) = dlsym(handle, "test");

    if ((error = dlerror()) != NULL)  {
        fprintf(stderr, "%s\n", error);
        exit(EXIT_FAILURE);
    }

    (*test)();
    dlclose(handle);
    exit(EXIT_SUCCESS);
}

ビルド

gcc -ldl -rdynamic main.c

出力:

[js@HOST2 dlopen]$ LD_LIBRARY_PATH=. ./a.out
here, in lib
here, i'm back
[js@HOST2 dlopen]$

この-rdynamicオプションは、使用されているシンボルの名前だけでなく、すべてのシンボルを動的シンボル テーブル (メモリにマップされている) に配置します。詳しくはこちらをご覧ください。もちろん、ライブラリとメイン プログラム間のインターフェイスを定義する関数ポインター (または関数ポインターの構造体) を提供することもできます。それは実際に私がおそらく選択する方法です。Windows で行うのはそれほど簡単ではないと他の人から聞いたことが-rdynamicあります。また、ライブラリとメイン プログラムの間の通信がよりクリーンになります (呼び出すことができるものとできないものを正確に制御できます)。ハウスキーピング。

于 2008-12-25T01:42:17.723 に答える
4

はい、ライブラリにその関数へのポインタを提供すると、ライブラリはメインプログラムで関数を実行/実行できると確信しています。

これは例です。コンパイルしていないので注意してください;)

/* in main app */

/* define your function */

int do_it( char arg1, char arg2);

int do_it( char arg1, char arg2){
  /* do it! */
  return 1;
}

/* some where else in main app (init maybe?) provide the pointer */
 LIB_set_do_it(&do_it);
/** END MAIN CODE ***/

/* in LIBRARY */

int (*LIB_do_it_ptr)(char, char) = NULL;

void LIB_set_do_it( int (*do_it_ptr)(char, char) ){
    LIB_do_it_ptr = do_it_ptr;
}

int LIB_do_it(){
  char arg1, arg2;

  /* do something to the args 
  ...
  ... */

  return LIB_do_it_ptr( arg1, arg2);
}
于 2008-12-25T01:35:28.863 に答える
1

dlopen()@litb で説明されているように、この関数は主に ELF 形式のオブジェクト ファイルを使用するシステムで提供されます。これはかなり強力で、ロードされたライブラリによって参照されるシンボルをメイン プログラムから満たすことができるかどうかを制御できます。通常、それらは満たされます。すべての共有ライブラリ ロード システムが柔軟であるとは限りません。コードの移植に関しては注意してください。

@hhafez によって概説されたコールバック メカニズムは、そのコードのねじれが解消されたので機能します。

于 2008-12-25T06:22:36.707 に答える