链接库的多个版本

Yer*_*ues 31 c c++ unix linux linker

我有一个应用程序静态链接来自第三方供应商VENDOR1的库libfoo的X版本.它还与来自不同第三方供应商VENDOR2的动态(共享)库libbar链接,该库将libfoo的Y版本与VENDOR1静态链接.

因此libbar.so包含libfoo.a的版本Y,我的可执行文件包含libfoo.a的版本X.libbar仅在内部使用libfoo,并且没有从我的应用程序传递到libbar的libfoo对象.

构建时没有错误,但在运行时app app出现故障.原因似乎是版本X使用具有不同的尺寸,他们的版本Y和运行时链接似乎混合了结构,它们习惯于通过.

VENDOR1和VENDOR2都是封闭源,所以我无法重建它们.

是否有建立/链接我的应用程序,使得它始终解析版本X和libbar的送花儿给人解析到版本Y和两个从未混合的方法吗?

Yer*_*ues 16

感谢所有的回复.我有一个似乎有效的解决方案.这是一个例子的详细问题.

在main.c中我们有:

#include <stdio.h>

extern int foo();

int bar()
{
    printf("bar in main.c called\n");
    return 0;
}

int main()
{
    printf("result from foo is %d\n", foo());
    printf("result from bar is %d\n", bar());
}
Run Code Online (Sandbox Code Playgroud)

在foo.c中我们有:

extern int bar();

int foo()
{
    int x = bar();
    return x;
}
Run Code Online (Sandbox Code Playgroud)

在bar.c我们有:

#include <stdio.h>

int bar()
{
    printf("bar in bar.c called\n");
    return 2;
}
Run Code Online (Sandbox Code Playgroud)

编译bar.c和foo.c:

$ gcc -fPIC -c bar.c
$ gcc -fPIC -c foo.c
Run Code Online (Sandbox Code Playgroud)

将bar.o添加到静态库:

$ ar r libbar.a bar.o
Run Code Online (Sandbox Code Playgroud)

现在使用foo.o创建一个共享库,并使用静态libbar.a进行链接

$ gcc -shared -o libfoo.so foo.o -L. -lbar
Run Code Online (Sandbox Code Playgroud)

编译main.c并链接共享库libfoo.so

$ gcc -o main main.c -L. -lfoo
Run Code Online (Sandbox Code Playgroud)

设置LD_LIBRARY_PATH以查找libfoo.so并运行main:

$ setenv LD_LIBRARY_PATH `pwd`
$ ./main
bar in main.c called
result from foo is 0
bar in main.c called
result from bar is 0
Run Code Online (Sandbox Code Playgroud)

请注意,调用main.c中的bar版本,而不是链接到共享库的版本.

在main2.c中我们有:

#include <stdio.h>
#include <dlfcn.h>


int bar()
{
    printf("bar in main2.c called\n");
    return 0;
}

int main()
{
    int x;
    int (*foo)();
    void *handle = dlopen("libfoo.so", RTLD_GLOBAL|RTLD_LAZY);
    foo = dlsym(handle, "foo");
    printf("result from foo is %d\n", foo());
    printf("result from bar is %d\n", bar());
}
Run Code Online (Sandbox Code Playgroud)

编译并运行main2.c(注意我们不需要显式链接libfoo.so):

$ gcc -o main2 main2.c -ldl
$ ./main2
bar in bar.c called
result from foo is 2
bar in main2.c called
result from bar is 0
Run Code Online (Sandbox Code Playgroud)

现在,共享库中的foo调用了main.c中的共享库和主调用栏

我不认为这种行为是直观的,使用dlopen/dlsym是更多的工作,但它确实解决了我的问题.

再次感谢您的评论.


bst*_*rre 6

尝试使用部分链接,以便使用libbar和libfoo-Y创建一个目标文件"partial.o".使用带有"--localize-symbols"的objcopy在libfoo-Y local中创建partial.o中的符号.您应该能够通过在libfoo-Y上运行nm并按摩输出来生成.然后获取修改后的partial.o并将其链接到您的应用程序.

我在vxWorks上用gcc工具链做了类似的事情,其中​​动态库不是复杂的,但需要两个版本的同一个库才能干净地链接到一个单片应用程序.