上篇文章是《msys2-gcc静态库使用》,本文来讲动态库,代码如下:
myTest.h :
int my_test(int a, int b);
myTest.c :
#include "myTest.h"
int my_test(int a, int b) {
return a + b;
}
myMath.h :
int add(int a, int b);
myMath.c:
#include "myMath.h"
#include "myTest.h"
int add(int a, int b) {
return my_test(a,b);
}
main.c :
#include <stdio.h>
#include "myMath.h"
int main()
{
int a = 3, b = 5;
printf("a+b=%d\n", add(3, 5));
return 0;
}
代码已经写好,先执行一下命令编译出 .o 后缀的文件。
gcc -c myMath.c -o myMath.o
gcc -c myTest.c -o myTest.o
gcc -c main.c -o main.o
- -fPIC:也可以写成 -fpic,功能是令 GCC 编译器生成动态链接库时,用相对地址表示库中各个函数和变量的存储位置。这样做的好处是,无论动态链接库被加载到内存的什么位置,都可以被多个程序(进程)同时调用;
msys2 环境操作下,gcc 生成的动态库是 xxx.dll 的,不是xxx.so。
要编译 mymath.dll 动态库 ,常规的做法是 gcc -c -fPIC myMath.c -o myMath.o
,把 C 代码编译成 object 文件,然后用 gcc -shared myMath.o -o mymath.dll -Wl,--out-implib,mymath.lib
把 object 文件转成 .dll 动态库文件。但我们现在有一个嵌套库 myTest ,而且不想暴露给别人,这时候应该如何编译。
- -Wl 表示后面的内容是ld 的参数,需要传递给 ld。 --out-implib,mymath.lib 表示让ld 生成一个名为 mymath.lib 的导入库。
其实跟静态库的编译差不多,把 myTest.o 文件加进去就行,gcc -shared myMath.o myTest.o -o mymath.dll -Wl,--out-implib,mymath.lib
。我们可以用以下两个不同的命令看一下生成的 mymath.dll 有什么区别。
第一个命令:gcc -shared myMath.o -o mymath_1.dll -Wl,--out-implib,mymath_1.lib
第二个命令:gcc -shared myMath.o myTest.o -o mymath_2.dll -Wl,--out-implib,mymath_2.lib
第一个命令是没加 myTest.o 的。
第一个命令直接报错了,那就不管跳过,咱们来看看 mymath_2.dll 跟 myMath.o myTest.o 的内容有没相同的地方。如下图:
可以看到 .so 文件,其实也是拥有 myTest.o 跟 myMath.o 里面的部分内容。所以无论是静态库还是动态库,他们都是把一堆 .o 文件合在一个文件里面,只不过动态库 .so 加了一个附加信息来实现动态加载,静态库加了一些附加信息来实现静态加载。
此时, myTest.o 跟 myMath.o 已经没用了,可以删除,只需要把 mymath_2.dll 给别人用就行,可以执行以下命令生成 main 可执行文件。
#第一种方式
gcc main.o mymath_2.dll -o main.exe
#第二种方式
gcc main.o -o main -lmymath_2 -L.
相关阅读:
由于笔者的水平有限, 加之编写的同时还要参与开发工作,文中难免会出现一些错误或者不准确的地方,恳请读者批评指正。如果读者有任何宝贵意见,可以加我微信 Loken1。