链接不同版本的共享库
Linking on different version of shared libraries
我有两个版本的共享库:库版本 2:
简单.h
#pragma once
int first(int x);
简单.c
#include "simple.h"
#include <stdio.h>
__asm__(".symver first_1_0,first@LIBSIMPLE_1.0");
int first_1_0(int x)
{
printf("lib: %sn", __FUNCTION__);
return x + 1;
}
__asm__(".symver first_2_0,first@@LIBSIMPLE_2.0");
int first_2_0(int x)
{
int y;
printf("lib: %dn", y);
printf("lib: %sn", __FUNCTION__);
return (x + 1) * 1000;
}
链接器版本脚本文件:
LIBSIMPLE_1.0{
global:
first;
local:
*;
};
LIBSIMPLE_2.0{
global:
first;
local:
*;
};
gcc -Wall -g -O0 -fPIC -c simple.c
gcc -shared simple.o -Wl,--version-script,script -o libsimple.so.2.0.0
和库版本 3:
简单.h
#pragma once
#ifdef SIMPLELIB_VERSION_3_0
int first(int x, int normfactor);
#else
int first(int x);
#endif //SIMPLELIB_VERSION_3_0
简单.c
#include "simple.h"
#include <stdio.h>
__asm__(".symver first_1_0,first@LIBSIMPLE_1.0");
int first_1_0(int x)
{
printf("lib: %sn", __FUNCTION__);
return x + 1;
}
__asm__(".symver first_2_0,first@LIBSIMPLE_2.0");
int first_2_0(int x)
{
printf("lib: %sn", __FUNCTION__);
return (x + 1) * 1000;
}
__asm__(".symver first_3_0,first@@LIBSIMPLE_3.0");
int first_3_0(int x, int normfactor)
{
printf("lib: %sn", __FUNCTION__);
return (x + 1) * normfactor;
}
链接器版本脚本文件:
LIBSIMPLE_1.0{
global:
first; second;
local:
*;
};
LIBSIMPLE_2.0{
global:
first;
local:
*;
};
LIBSIMPLE_3.0{
global:
first;
local:
*;
};
gcc -Wall -g -O0 -fPIC -c simple.c
gcc -shared simple.o -Wl,--version-script,script -o libsimple.so.3.0.0
所以我最终有两个不同的库。接下来,我创建一个简单的应用程序,最终我想链接到库版本 3,因此在其中我使用函数 first(),它接受两个参数:
主.c
#include <stdio.h>
#include "simple.h"
int main(int argc, char* argv[])
{
int nFirst = first(1, 10);
printf("First(1) = %dn", nFirst);
}
我使用以下命令编译应用程序:
gcc -g -Wall -DSIMPLELIB_VERSION_3_0 -c main.c
然后,偶然地,我没有链接到库版本 3,而是链接到库版本 2。我预计链接会失败,但它通过了,并且应用程序正在工作。
gcc main.o -Wl,-L. -lsimple.2.0.0 -Wl,-R. -o demo
所以我的问题是:
- 是因为库导出名称为"函数"的符号,并且应用程序尝试链接到相同的符号名称,这就是为什么链接器没有抱怨,只是链接到库版本 2 的原因?
- 我认为由于 c++ 会破坏符号名称,因此不会发生这样的事情,并且链接器不会链接到库版本 2。所以我尝试了所有相同的方法,但我尝试使用 g++ 而不是 gcc 编译器。一切都很顺利,直到我尝试将应用程序链接到库,并且收到未解决的链接错误。不知道为什么。
附言对不起,大量的代码。我试图说清楚。 谢谢
是因为库导出名称为"函数"的符号,并且应用程序尝试链接到相同的符号名称,这就是为什么链接器没有抱怨,只是链接到库版本 2 的原因?
是的,由于普通 C 没有函数重载,因此不需要重整,因此只有函数名称将用作链接的符号。最后,您的应用程序代码想要与function
链接,并且您的库代码导出function
,这足以让链接器满意(即使从二进制接口的角度来看它无效)。
我认为由于 c++ 会破坏符号名称,因此不会发生这样的事情,并且链接器不会链接到库版本 2。所以我尝试了所有相同的方法,但我尝试使用 g++ 而不是 gcc 编译器。一切都很顺利,直到我尝试将应用程序链接到库,并且收到未解决的链接错误。不知道为什么。
是的,由于名称重整,此问题不应在C++中发生。但是,仅当您同时具有应用程序代码和库代码C++或者以正确的方式桥接 C 和C++代码时,才如此。
很难说(没有完整列表)当你使用 g++ 时在你的情况下发生了什么,但从它的外观来看,你最终在 C++ 中拥有应用程序代码,而库代码仍然是 C 格式。如果是这种情况,您的应用程序代码现在将希望与损坏的function
链接,而您的库代码仍导出未修改的function
。
要验证这一点,您可以使用以下内容检查对象文件:
nm main.o
。并确切地看到它想要什么样的符号。如果你会得到这样的东西:
...
U _Z3functionii
...
。而不是:
...
U function
...
。那么情况就是这样。
要"修复"此问题并使C++应用程序代码与库代码中的未修改function
链接,您需要将函数原型声明为extern "C"
。
- 如何以编程方式查找加载的共享库的版本?
- 使用共享库版本支持不同 ABI 的最佳实践是什么?
- 正在加载共享对象:文件中未定义版本Qt_5
- 如何处理加载错误的共享库版本的情况
- 如何链接到与 Linux 中不同版本的 boost 链接的共享库
- 共享指针,C 版本的原子操作
- 如果您用新版本覆盖共享库(当前由程序映射)会发生什么
- G 无法链接共享对象的静态版本
- 链接不同版本的共享库
- 如何在本机C++(Windows 7及以前版本)和通用C++(Windows 8及以后版本)应用程序之间共享代码
- C/C++ 尝试创建共享库时出错.创建库的静态版本时不会发生错误
- 共享内存段在提升版本和编译器版本之间是否兼容
- 确定用于在*ix操作系统上构建共享对象的编译器和版本
- 简单的加法示例:共享内存版本的reduce执行速度比全局内存慢
- 共享库:无版本信息
- 在OS X(不同版本/配置文件)上的OpenGL上下文之间共享数据
- 确保内部共享库版本正确
- 是否可能获取共享对象的版本?
- 当我包含一个共享库时,我的可执行文件正在寻找它的两个版本
- Linux上的共享库版本和可执行文件