5

我是 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 中的所有公共方法,但是我如何“通过”这些结构呢?

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

4

1 回答 1

5

所以你有 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_ptrNewLib 创建完成后,当然可以替换 OldLib。

于 2013-01-21T23:12:36.850 回答