本文介绍了链接库的多个版本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have an application that statically links with version X of a library, libfoo, from thirdparty vendor, VENDOR1. It also links with a dynamic (shared) library, libbar, from a different thirdparty vendor, VENDOR2, that statically links version Y of libfoo from VENDOR1.

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

So libbar.so contains version Y of libfoo.a and my executable contains version X of libfoo.alibbar only uses libfoo internally and there are no libfoo objects passed from my app to libbar.

在构建时没有错误,但在运行时应用程序段错误.原因似乎是版本 X 使用的结构与版本 Y 的大小不同,并且运行时链接器似乎混淆了哪个由哪个使用.

There are no errors at build time but at runtime the app seg faults. The reason seems to be that version X uses structures that have a different size they version Y and the runtime linker seems to be mixing up which get used by which.

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

Both VENDOR1 & VENDOR2 are closed source so I cannot rebuild them.

有没有办法构建/链接我的应用程序,使其始终解析为 X 版本,而 libbar 始终解析为 Y 版本,并且两者从不混合?

Is there a way to build/link my app such that it always resolves to version X and libbar alway resolves to version Y and the two never mix?

推荐答案

感谢大家的回复.我有一个似乎有效的解决方案.下面用一个例子详细说明问题.

Thanks for all the responses. I have a solution that seem to be working.Here's the problem in detail with an example.

在 main.c 我们有:

In main.c we have:

#include <stdio.h>

extern int foo();

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

int main()
{
    printf("result from foo is %d
", foo());
    printf("result from bar is %d
", bar());
}

在 foo.c 我们有:

In foo.c we have:

extern int bar();

int foo()
{
    int x = bar();
    return x;
}

在 bar.c 中我们有:

In bar.c we have:

#include <stdio.h>

int bar()
{
    printf("bar in bar.c called
");
    return 2;
}

编译 bar.c 和 foo.c:

Compile bar.c and foo.c:

$ gcc -fPIC -c bar.c
$ gcc -fPIC -c foo.c

将 bar.o 添加到静态库:

Add bar.o to a static library:

$ ar r libbar.a bar.o

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

Now create a shared library using foo.o and link with static libbar.a

$ gcc -shared -o libfoo.so foo.o -L. -lbar

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

Compile main.c and link with shared library libfoo.so

$ gcc -o main main.c -L. -lfoo

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

Set LD_LIBRARY_PATH to find libfoo.so and run 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

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

Notice that the version of bar in main.c is called, not the version linked into the shared library.

在 main2.c 我们有:

In main2.c we have:

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


int bar()
{
    printf("bar in main2.c called
");
    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
", foo());
    printf("result from bar is %d
", bar());
}

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

Compile and run main2.c (notice we dont need to explicitly link with 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

现在共享库中的 foo 调用共享库中的 bar 和 main.c 中的 main 调用 bar

Now foo in the shared library calls bar in the shared library and main calls bar in main.c

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

I don't think this behaviour is intuitive and it is more work to use dlopen/dlsym, but it does resolve my problem.

再次感谢您的评论.

这篇关于链接库的多个版本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-18 12:59