c - 共享库 (.so) 如何调用在其加载程序代码中实现的函数?

标签 c linux gcc shared-libraries

我有一个我实现的共享库,并希望 .so 调用在加载库的主程序中实现的函数。

假设我有 main.c(可执行文件),其中包含:

void inmain_function(void*);
dlopen("libmy.so");

在 my.c(libmy.so 的代码)中,我想调用 inmain_function:

inmain_function(NULL);

共享库如何调用 inmain_function 而不管 inmain_function 是在主程序中定义的。

注意:我想从 my.c 调用 main.c 中的一个符号,而不是相反,这是常见的用法。

最佳答案

您有两个选项,您可以从中选择:

选项 1:从可执行文件中导出所有符号。 这是一个简单的选项,只是在构建可执行文件时,添加一个标志 -Wl,--export-dynamic。这将使所有函数都可用于库调用。

选项 2:创建一个包含函数列表的导出符号文件,并使用 -Wl,--dynamic-list=exported.txt。这需要一些维护,但更准确。

演示:简单的可执行文件和动态加载的库。

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

void exported_callback() /*< Function we want to export */
{
    printf("Hello from callback!\n");
}

void unexported_callback() /*< Function we don't want to export */
{
    printf("Hello from unexported callback!\n");
}

typedef void (*lib_func)();

int call_library()
{
   void     *handle  = NULL;
   lib_func  func    = NULL;
   handle = dlopen("./libprog.so", RTLD_NOW | RTLD_GLOBAL);
   if (handle == NULL)
   {
       fprintf(stderr, "Unable to open lib: %s\n", dlerror());
       return -1;
   }
   func = dlsym(handle, "library_function");

   if (func == NULL) {
       fprintf(stderr, "Unable to get symbol\n");
      return -1;
   }

   func();
   return 0;
}

int main(int argc, const char *argv[])
{
    printf("Hello from main!\n");
    call_library();
    return 0;
}

库代码(lib.c):

#include <stdio.h>
int exported_callback();

int library_function()
{
    printf("Hello from library!\n");
    exported_callback();
    /* unexported_callback(); */ /*< This one will not be exported in the second case */
    return 0;
}

所以,首先构建库(这一步没有区别):

 gcc -shared -fPIC lib.c -o libprog.so

现在构建导出所有符号的可执行文件:

 gcc -Wl,--export-dynamic main.c -o prog.exe -ldl

运行示例:

 $ ./prog.exe
 Hello from main!
 Hello from library!
 Hello from callback!

导出的符号:

 $ objdump -e prog.exe -T | grep callback
 00000000004009f4 g    DF .text  0000000000000015  Base        exported_callback
 0000000000400a09 g    DF .text  0000000000000015  Base        unexported_callback

现在导出列表(exported.txt):

{
    extern "C"
    {
       exported_callback;
    };
};

构建并检查可见符号:

$ gcc -Wl,--dynamic-list=./exported.txt main.c -o prog.exe -ldl
$ objdump -e prog.exe -T | grep callback
0000000000400774 g    DF .text  0000000000000015  Base        exported_callback

关于c - 共享库 (.so) 如何调用在其加载程序代码中实现的函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17081131/

相关文章:

c++ - 使用套接字 rfcomm 的蓝牙连接

c++ - 我必须做什么才能在数据区执行代码,(段保护)

java - 如何使用命令行在 Linux 下使用 Java 构建 OpenCV?(将在 MapReduce 中使用它)

gcc - GNU 标准库命名约定

c - 为什么我需要标题?

c - 是否有一种故障安全方法来确定 C 中指针的对齐/尾随位?

c++ - DirectX:如何更改按钮对象的字体大小?

html - perl:在 Linux 上创建 PDF Avery 标签?

database - 无法启动 Alfresco 3.4.4(启动 postgresql 时出错)

c++ - Linux 用户空间 header 无法使用 g++ 进行编译