c - 在 C 中使用 dlopen 时,是否有避免 dlsym 的优雅方法?

标签 c shared-libraries function-pointers dlopen

我需要动态打开一个共享库lib.so如果在运行时满足特定条件。该库包含约 700 个函数,我需要加载它们的所有符号。

一个简单的解决方案是定义指向lib.so 中包含的所有符号的函数指针。 , 使用 dlopen 加载库最后使用 dlsym 获取所有符号的地址.然而,考虑到函数的数量,实现该解决方案的代码非常繁琐。

我想知道是否存在更优雅和简洁的解决方案,也许可以适当使用宏来定义函数指针。谢谢!

最佳答案

您可以为 dlopen-ed 库中的所有符号自动生成蹦床函数。 Trampolines 将被视为应用程序中的正常功能,但会在内部重定向到库中的真实代码。这是一个简单的 5 分钟 PoC:

$ cat lib.h
// Dynamic library header
#ifndef LIB_H
#define LIB_H
extern void foo(int);
extern void bar(int);
extern void baz(int);
#endif

$ cat lib.c
// Dynamic library implementation
#include <stdio.h>

void foo(int x) {
  printf("Called library foo: %d\n", x);
}

void bar(int x) {
  printf("Called library baz: %d\n", x);
}

void baz(int x) {
  printf("Called library baz: %d\n", x);
}

$ cat main.c
// Main application
#include <dlfcn.h>
#include <stdio.h>

#include <lib.h>

// Should be autogenerated
void *fptrs[100];
void init_trampoline_table() {
  void *h = dlopen("./lib.so", RTLD_LAZY);
  fptrs[0] = dlsym(h, "foo");
  fptrs[1] = dlsym(h, "bar");
  fptrs[2] = dlsym(h, "baz");
}

int main() {
  init_trampoline_table();
  printf("Calling wrappers\n");
  foo(123);
  bar(456);
  baz(789);
  printf("Returned from wrappers\n");
  return 0;
}

$ cat trampolines.S
  // Trampoline code.
  // Should be autogenerated. Each wrapper gets its own index in table.
  // TODO: abort if table wasn't initialized.

  .text

  .globl foo
foo:
  jmp *fptrs(%rip)

  .globl bar
bar:
  jmp *fptrs+8(%rip)

  .globl baz
baz:
  jmp *fptrs+16(%rip)

$ gcc -fPIC -shared -O2 lib.c -o lib.so
$ gcc -I. -O2 main.c trampolines.S -ldl
$ ./a.out
Calling wrappers
Called library foo: 123
Called library baz: 456
Called library baz: 789
Returned from wrappers

请注意,main.c 中的应用程序代码仅使用本地函数(包装库函数)并且根本不需要弄乱函数指针(除了在启动时初始化重定向表之外,这应该无论如何都是自动生成的代码)。

编辑:我创建了一个独立的工具 Implib.so 来自动创建 stub 库,如上例所示。结果证明这或多或少等同于众所周知的 Windows DLL 导入库。

关于c - 在 C 中使用 dlopen 时,是否有避免 dlsym 的优雅方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45917816/

相关文章:

c - 如何使用 ASSERT 检查字符串是否包含字符?

c++ - 为什么自由函数指针总是指针类型,而成员函数指针实际上不是指针?

c - 提供函数指针时取消引用指向不完整类型的指针

不带参数的 C++ 存储函数

c - 调用 system() 后程序不执行任何操作

c - 实时压缩32位RGBA图像数据

c - 三重嵌套循环的时间复杂度?

c++ - eclipse C/C++ : Using static/shared library project in executable project

c++ - 创建包含大数据的共享库的最佳实践

linux - 当前线程执行的共享对象文件路径