【发布时间】:2017-09-07 23:43:25
【问题描述】:
我有一个特殊的情况,使用来自两个不同静态库的函数,是这样的:
我有一个模块“Fun”,它有一个函数“Fun()”和用于工作的静态变量。我有一个静态库“LibA.a”,它有一个使用模块“Fun”的函数“LibA()”。我在静态库“Fun.a”中制作了“Fun”模块。
换句话说:
Fun.a include Func.c
LibA.a include LibA.c and Fun.c
当在主调用中使用 Fun.c 的函数 LibA 时,它从 Fun.a 而不是从 LibA 执行。
问题在于 Fun.c 中的静态变量是从 main 和 LibA 使用的。
是否可以使 LibA 使用包含在库 LibA.a 中的 Fun 而不是 Fun.a 库中的 Fun?因为有两个不同的 Func() 实例。
我做这个例子:
Fun.h
extern int Fun( void );
Fun.c
#include <stdio.h>
#include "Fun.h"
static int value = 0;
int Fun( void )
{
#ifdef FUN
printf( "Call from Fun.a\n" );
#endif
#ifdef LIBA
printf( "Call from LibA.a\n" );
#endif
return value++;
}
LibA.h
extern void LibA( void );
LibA.c
#include <stdio.h>
#include "LibA.h"
#include "Fun.h"
void LibA( void )
{
printf( "LibA->Fun:%d\n", Fun( ) );
}
main.c
#include <stdio.h>
#include "LibA.h"
#include "Fun.h"
int main()
{
printf("Lib Example\n");
LibA( );
LibA( );
LibA( );
printf( "Main->Fun:%d\n", Fun( ) );
printf( "Main->Fun:%d\n", Fun( ) );
printf( "Main->Fun:%d\n", Fun( ) );
LibA( );
return 0;
}
这个例子的输出是:
Lib Example
Call from Fun.a
LibA->Fun:0
Call from Fun.a
LibA->Fun:1
Call from Fun.a
LibA->Fun:2
Call from Fun.a
Main->Fun:3
Call from Fun.a
Main->Fun:4
Call from Fun.a
Main->Fun:5
Call from Fun.a
LibA->Fun:6
而我想要的输出是这样的:
Lib Example
Call from LibA.a
LibA->Fun:0
Call from LibA.a
LibA->Fun:1
Call from LibA.a
LibA->Fun:2
Call from Fun.a
Main->Fun:0
Call from Fun.a
Main->Fun:1
Call from Fun.a
Main->Fun:2
Call from LibA.a
LibA->Fun:3
为了制作 Fun 静态库,我使用了这个:
gcc-6 -c -x c Fun.c -g2 -gdwarf-2 -o Fun.o" -Wall -O0 -DFUN -std=c11
ar -rsc libFun.a Fun.o
为了制作 LibA 静态库,我使用这个:
gcc-6 -c -x c Fun.c -g2 -gdwarf-2 -o Fun.o -O0 -DLIBA -std=c11
gcc-6 -c -x c LibA.c -g2 -gdwarf-2 -o LibA.o -O0 -DLIBA -std=c11
ar -rsc libLibA.a Fun.o LibA.o
为了做主要的例子,我用这个:
gcc-6 -c -x c main.c -g2 -gdwarf-2 -o main.o -O0 -std=c11
gcc-6 -o main.out -Wl,--no-undefined -Wl,-L./ -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack main.o -lFun -lLibA
【问题讨论】:
-
如果静态库中有多个同名函数定义,链接器将使用它在静态库中可以找到的第一个函数定义。不要滥用它。
-
亲爱的 Serge,我知道链接器是如何工作的,问题是链接器中是否存在任何参数或解决此问题的其他方法。
-
不,没有这样的参数。链接器中的所有绑定都是通过链接文件的符号表中的名称完成的。如果您有重复的全局名称。它会混淆链接器。因此,如果您将链接“.o”文件而不是库,则链接器将大声抱怨链接错误。在静态库的情况下,如果找到符号定义,它将不查找符号定义。不过,您可以使用动态库玩一些技巧。
标签: c gcc static-libraries