加载的库函数如何在主应用程序中调用符号?

时间:2008-12-25 01:30:11

标签: c module dlopen

加载共享库时,通过函数dlopen()打开,有没有办法在主程序中调用函数?

3 个答案:

答案 0 :(得分:19)

dlo.c代码(lib):

#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选项将所有符号放在动态符号表中(映射到内存中),而不仅仅是所用符号的名称。进一步阅读here。当然,您还可以提供定义库与主程序之间接口的函数指针(或函数指针结构)。这实际上是我可能选择的方法。我从其他人那里听说在窗口中执行-rdynamic并不是那么容易,它也可以使库和主程序之间的通信更加清晰(你可以对可以调用的内容进行精确控制,而不是)但它也需要更多的管家。

答案 1 :(得分: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);
}

答案 2 :(得分:1)

@litb讨论的dlopen()函数主要在使用ELF格式目标文件的系统上提供。它功能非常强大,可让您控制是否可以从主程序中满足加载库引用的符号,并且通常可以让它们满足。并非所有共享库加载系统都具有灵活性 - 请注意是否需要移植代码。

@hhafez概述的回调机制现在可以解决该代码中的问题。