如何在C语言共享库中使用extern符号及编译相关测试代码
嘿,我来一步步帮你搞定编译共享库和extern符号的问题~
一、编译创建共享库的步骤
要把你的代码编译成可用的共享库,分三步就能完成,全程用gcc命令操作:
- 编译
add.c为位置无关目标文件(PIC)
共享库要求代码是位置无关的,这样加载时可以映射到内存的任意地址。执行这条命令:
gcc -c -fPIC add.c -o add.o
其中-c表示只编译不链接,-fPIC是生成位置无关代码的关键参数。
- 编译
answer.c为位置无关目标文件
同样的逻辑,给answer.c也生成PIC目标文件:
gcc -c -fPIC answer.c -o answer.o
- 链接生成共享库
把两个目标文件打包成共享库,比如命名为libtest.so:
gcc -shared add.o answer.o -o libtest.so
-shared参数会告诉gcc生成共享库格式的文件。
测试共享库(可选)
如果想验证库能不能正常工作,你可以写一个主程序main.c,实现answer.c里extern声明的myvar函数:
#include <stdio.h> // 引用共享库中的answer函数 extern int answer(); // 实现共享库需要的myvar函数 int myvar() { return 100; } int main() { int result = answer(); printf("Final result: %d\n", result); return 0; }
然后编译主程序并链接共享库:
gcc main.c -L. -ltest -o test_program
-L.让gcc在当前目录查找共享库,-ltest表示链接libtest.so。
运行程序时,需要临时告诉系统共享库的位置:
LD_LIBRARY_PATH=. ./test_program
运行后你会看到预期的输出:
myvar:100 1Library is initialized Final result: 42
二、C共享库中extern符号的使用说明
先给你把extern的核心作用讲明白:它是一个声明,告诉编译器“这个函数/变量的定义不在当前文件/库中,而是在外部模块(比如主程序、其他库)里”。
你的例子中的extern用法
在answer.c里写的extern int myvar();,就是明确告诉编译器:myvar这个函数的实现不在当前的共享库(add.c和answer.c)里,得等加载这个库的程序来提供定义。
这里有几个关键细节要记牢:
- 弱引用特性:共享库中的extern符号属于“弱引用”,编译共享库时不会因为找不到定义报错,只有在运行时,如果加载库的程序没提供这个符号的定义,才会抛出
undefined symbol的错误。 - 必须外部实现:用这个共享库的程序必须实现
myvar函数,否则程序运行会直接失败,就像我们测试用的main.c里,必须写int myvar() { return 100; }才能让共享库正常工作。 - 反向引用也可行:反过来,如果共享库中定义了某个函数或全局变量,主程序也可以用
extern来引用。比如你可以在主程序里写extern void setSummand(int);直接调用共享库的函数(不过更规范的做法是通过头文件add.h来声明)。
小提醒
- 尽量别用extern引用共享库的全局变量(比如
gSummand),全局变量会破坏代码的封装性,最好通过函数接口(比如setSummand)来操作。 - 如果你的共享库需要多个外部符号,一定要确保所有extern声明的符号都在加载程序中实现,不然运行时会直接报错。
内容的提问来源于stack exchange,提问作者thebworld
相关产品推荐
相关产品推荐

