我有两个版本的共享库: 库版本2:
simple.h
#pragma once
int first(int x);
simple.c
#include "simple.h"
#include <stdio.h>
__asm__(".symver first_1_0,first@LIBSIMPLE_1.0");
int first_1_0(int x)
{
printf("lib: %s\n", __FUNCTION__);
return x + 1;
}
__asm__(".symver first_2_0,first@@LIBSIMPLE_2.0");
int first_2_0(int x)
{
int y;
printf("lib: %d\n", y);
printf("lib: %s\n", __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:
simple.h
#pragma once
#ifdef SIMPLELIB_VERSION_3_0
int first(int x, int normfactor);
#else
int first(int x);
#endif //SIMPLELIB_VERSION_3_0
simple.c
#include "simple.h"
#include <stdio.h>
__asm__(".symver first_1_0,first@LIBSIMPLE_1.0");
int first_1_0(int x)
{
printf("lib: %s\n", __FUNCTION__);
return x + 1;
}
__asm__(".symver first_2_0,first@LIBSIMPLE_2.0");
int first_2_0(int x)
{
printf("lib: %s\n", __FUNCTION__);
return (x + 1) * 1000;
}
__asm__(".symver first_3_0,first@@LIBSIMPLE_3.0");
int first_3_0(int x, int normfactor)
{
printf("lib: %s\n", __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(),它接受两个参数:
的main.c
#include <stdio.h>
#include "simple.h"
int main(int argc, char* argv[])
{
int nFirst = first(1, 10);
printf("First(1) = %d\n", 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
所以我的问题是:
P.S。很抱歉有大量代码。我试图说清楚。 谢谢
答案 0 :(得分:2)
是因为库导出带有名称'function'的符号,并且应用程序尝试链接到相同的符号名称,这就是链接器没有抱怨的原因,只是链接到库版本2?
是的,因为普通C没有函数重载,所以不需要修改,因此只有函数名称将用作链接的符号。最后,您的应用程序代码想要与function
和您的库代码导出function
,这足以让链接器满意(即使它从二进制接口的角度看无效。)
我认为,因为c ++破坏了符号名称,所以这种情况不会发生,并且链接器也不会链接到库版本2.所以我尝试了所有相同的,但我尝试使用g ++而不是gcc编译器。一切顺利,直到我试图将应用程序链接到库,我收到未解决的链接错误。无法弄清楚原因。
是的,由于名称错误,C ++中不应该出现此问题。但是,只有在C ++中同时包含应用程序代码和库代码,或者以正确的方式桥接C和C ++代码时,才会出现这种情况。
很难说(没有完整列表)当你使用g ++时你的情况发生了什么,但从它的外观来看,你最终在C ++和库代码中应用程序代码 / em>仍在C中。如果是这种情况,您的应用程序代码现在想要与错误的function
链接,而您的库代码仍然导出未编译的{{ 1}}。
要验证这一点,您可以使用以下内容检查目标文件:
function
...并确切地看到它想要什么样的符号。如果你得到这样的东西:
nm main.o
...而不是:
...
U _Z3functionii
...
......那就是这种情况。
要“修复”此问题并使用库代码中未编译的...
U function
...
进行C ++ 应用程序代码链接,您需要将函数原型声明为{ {1}}。