【问题标题】:how to create my thin wrapper shared library around the c/c++ shared libraries in linux如何在 linux 中围绕 c/c++ 共享库创建我的瘦包装共享库
【发布时间】:2021-09-24 22:08:24
【问题描述】:

问题陈述。有两个共享库 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

这个想法是,通过设置LD_LIBRARY_PATH,可以通过换入不同版本的 libMy.so(基于 libA.so 或 libB.so)来使用相同的内置 main1、main2。

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

问题是,main1用什么样的linker options只直接依赖libMy.so,而libMy.so直接依赖libA.so或libB.so,实现provider的可交换。

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

【问题讨论】:

  • 如果您使用odbcunix,您的程序将仅依赖于libodbc.so,它将通过基于odbcinst.ini 的dlopen/dlsym 加载实际驱动程序(例如,它是Oracle 的libsqora.so) .
  • 澄清。要求是不要更改任何代码或第三方库。唯一的变化是链接。本质上,不是 main1 链接到 LibA.so,而是目标是 main1 链接到中间人 libMy.so。一个版本的 libMy.so 链接到 libA.so 并交付给一些客户。对于其他客户,请提供另一个版本的 libMy.so 以链接到 libB.so。问题是,“嗨,链接器,你能在 main1 文件中只提到 libMy.so 吗?libMy.so 知道哪个 libA.so 或 libB.so 由加载器重新定位所有符号”。什么链接器选项?

标签: linux odbc shared-libraries import-libraries


【解决方案1】:

您确实需要制作一个瘦包装库,它提供与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);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-10-26
    • 1970-01-01
    • 1970-01-01
    • 2020-11-18
    • 1970-01-01
    • 2012-12-19
    • 2020-01-03
    • 1970-01-01
    相关资源
    最近更新 更多