1

问题陈述。有两个共享库 libA.so 和 libB.so,它们都公开了相同的函数集。现在,我有很多小程序(比如 100 个)需要链接到 libA.so 或 libB.so。

选项 1.构建两组这样的程序,一组链接到 libA.so,另一组链接到 libB.so。

选项 2.创建一个瘦包装共享库 libMy.so 并链接为:

gcc -shared -o libMy.so libA.so
gcc -o main1 -L. -lMy main1.o

这个想法是相同的内置 main1,main2 可以通过设置LD_LIBRARY_PATH.

问题是在链接时,main1,main2,... 仍然引用 libA.so,除了 libMy.so,如命令readelf -D main1所示。

问题是,main1 用什么样的链接器选项只直接依赖于 libMy.so,而 libMy.so 直接依赖于 libA.so 或 libB.so,实现可交换提供者。

实际示例 libA.so 和 libB.so 是两个 odbc 驱动程序,一个用于 oracle,另一个用于 postgresql。如何以独立于数据库的方式链接可执行文件?

4

1 回答 1

0

您确实需要制作一个瘦包装库,它提供与libA.so/相同的接口libB.so。该库将通过 内部加载真正的实现dlopen,在其中定位方法的实现,dlsym并在运行时向它们调度调用。您的应用程序将只需要链接并且不会libwrapper.so意识到实际的实现。

这样的包装器库可以手动编写,也可以通过Implib.so包装器生成器编写:

$ implib-gen.py --dlopen-callback=mycallback libxyz.so

macallback回调将决定加载哪个库:

$ cat mycallback.c
#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>

#ifdef __cplusplus
extern "C"
#endif

void *mycallback(const char *lib_name) {
  lib_name = lib_name;  // Please the compiler
  void *h = dlopen(some_condition ? "libA.so" : "libB.so",
                   RTLD_LAZY);
  if (h)
    return h;
  fprintf(stderr, "dlopen failed: %s\n", dlerror());
  exit(1);
}
于 2021-07-16T15:39:22.267 回答