【问题标题】:Extend a dynamic linked shared library?扩展动态链接共享库?
【发布时间】:2013-01-21 23:01:07
【问题描述】:

我是 C 的新手,很抱歉我缺乏知识(我的 C 书真的很庞大 :)

我想用封闭源代码扩展一个共享库 (libcustomer.so),但公开的 api。

这样的事情可能吗?

  1. 将 libcustomer.so 重命名为 liboldcustomer.so
  2. 创建一个扩展的共享库 libcustomer.so(因此其他人隐式使用扩展的)
  3. 通过 -loldcustomer 将 liboldcustomer.so 链接到我的扩展 libcustomer.so
  4. 将任何未额外实现的方法直接转发到旧的“liboldcustomer.so”

我不认为它会那样工作(名称被编译到 .so 中,不是吗?)。 但是有什么选择呢?

对于#4:有没有一种通用的方法可以做到这一点,还是我必须编写一个像旧方法一样命名的方法并转发调用(如何?)?

因为原始的 libcustomer.so (=liboldcustomer.so) 会不时更改,所以所有这些东西都应该动态工作。

出于安全原因,我们的系统没有 LD_PRELOAD(否则我会采用 :( )。

考虑扩展验证检查和一些更好的 NPE 处理。

提前感谢您的帮助!

编辑:

我只是在实现我的扩展,如答案所示,但我目前有一个未处理的案例:

如何“代理”扩展库中的结构?

例如我有这个:

客户.h:

struct customer;

客户.c:

struct customer {
    int children:1;
    int age;
    struct house *house_config;
};

现在,在我的 customer-extension.c 中,我正在编写来自 customer.c 的所有公共方法,但我如何“传递”这些结构?

非常感谢您的时间和帮助!

【问题讨论】:

  • 您的第一个附加问题的答案已经给出。第二个密切相关 - C/C++ 不包含任何二进制元信息,如 Java/.NET,因此您无法猜测“客户”结构的定义可能是什么样子。即使您记住此结构中字段的类型和名称,编译器设置也可能存在问题 - 例如,字段对齐。

标签: c shared-libraries extending


【解决方案1】:

所以你有 OldLib 和

void func1();
int  func2();
... etc

第 4 步可能看起来像使用一些静态初始化创建另一个库。

使用内容创建 NewLib:

void your_func1();

void (*old_func1_ptr)() = NULL;
int  (*old_func2_ptr)() = NULL;

void func1()
{
    // in case you don't have static initializers, implement lazy loading
    if(!old_func1_ptr)
    {
       void* lib = dlopen("OldLibFileName.so", RTLD_NOW);
       old_func1_ptr = dlsym(lib, "func1");
    }

    old_func1_ptr();
}

int func2()
{
    return old_func2_ptr();
}

// gcc extension, static initializer - will be called on .so's load
// If this is not supported, then you should call this function
// manually after loading the NewLib.so in your program.
// If the user of OldLib.so is not _your_ program,
// then implement lazy-loading in func1, func2 etc. - check function pointers for being NULL
// and do the dlopen/dlsym calls there.
__attribute__((constructor))
void static_global_init()
{
   // use dlfcn.h
   void* lib = dlopen("OldLibFileName.so", RTLD_NOW);

   old_func1_ptr = dlsym(lib, "func1");
   ...
}

如果您对旧 API 有一些描述,则可以自动生成 static_global_init 和所有 func_ptr。 NewLib创建后,当然可以替换OldLib。

【讨论】:

  • 你好 Viktor,我已经删除了旧问题,因为它们在其他帖子中得到了回答。您(或其他人)能告诉我如何代理“结构”吗?我已经用一个具体的例子扩展了我的问题。非常感谢。
  • 乍一看,'pcm*' 和 'int' 之间没有主要区别。 'int' 更容易输入,所以我选择在我的示例中使用 'int'。我认为您可以“传递”指向结构甚至结构本身的指针。只需使用 .so 库随附的 .h 文件中的“原始”结构定义。
  • 此时,我还了解到,应该只导出用typedef 装饰的结构:) (cs.swarthmore.edu/~newhall/unixhelp/howto_C_libraries.htm)。感谢您的所有帮助!
  • 我现在已经开发了我的扩展库,它可以转发大约 35 个函数。它就像一个魅力(与你的构造函数:)!再次感谢 Viktor,这是我在 SO 上收到的最佳答案之一。
  • 不久前我第一次学习“构造函数”的东西。我很乐意分享这些知识。希望我们在 15 年前都有这么棒的网站)))
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多