创建C语言静态库与动态库

原创
2016/10/24 21:39
阅读数 2.7K

    “程序库”就是包含了一些同音函数的数据和二进制可执行机器码的文件。这些文件是目标文件的一种,其不能单独执行。但是如果将其与其他的可执行代码结合起来就可以执行。这些目标文件通常可以完成同一类功能,他们可以作为其他执行程序的一部分来执行。由于库的存在,使得用户编写的程序模块化更强,从而可以加强程序的再编译,提高代码的复用性。

从链接方式上,程序库可分为静态库和动态库(共享库)两种:

  • 静态库:是在执行程序运行前就已经加入到执行码中,成为执行程序的一部分来执行。
  • 动态库:是在执行程序启动是加载到执行程序中,可以被多个执行程序共享使用。

一、静态库

1.静态库的概念

静态库是一些目标代码的集合。linux环境下的静态库目标文件一般以.a作为扩展名。Linux环境下使用ar命令创建一个静态库。静态库的优点在于使用简单,编译快速,静态库在应用程序生成时,已经编译成为可重定位的目标文件,因此可不必再编译。

由于静态库在编译时已经复制到可执行代码段中,所以不需要像使用动态库那样在程序加载时再次链接。

2.创建静态库

创建一个四则运算的静态库:

(1)四则运算的代码为:

/* 计算加法的函数 */
int add(int a, int b)
{
  return a + b;
}

/* 计算减法的运算 */
int sub(int a, int b)
{
  return a - b;
}

/* 计算乘法的运算 */
int mul(int a, int b)
{
  return a * b;
}

/* 计算除法的运算 */
int div(int a, int b)
{
  return a / b; 
}

(2)在shell中编译源文件,生成一个可重定位的目标文件:

gcc -c static_lib.c

生成的目标文件为:

static_lib.o

(3)Linux下使用工具ar创建一个静态库,或者将目标文件加入到一个已经存在的静态库中,使用方法如下:

ar rcs 静态库名 目标文件1 目标文件2...目标文件n

该命令将目标文件1~n加入到指定的静态库中。如果该静态库不存在,则创建静态库文件。其中ar工具的参数rcs起到了重要的作用。这三个参数分别表示:

  • 参数r:把列表中的目标文件加入到静态库中
  • 参数c:若指定的静态库不存在,则创建该库文件
  • 参数s:更新静态库文件的索引,是指包含新加入的目标文件的内容

现在使用刚生成的.o文件创建一个静态库:

ar rcs libstatic_lib.a static_lib.o

这样就生成了一个新的静态库:

libstatic_lib.a

3.使用静态库

静态库创建成功后,需要链接到应用程序中使用。应用程序可以引用该库中的函数或者全局变量。为了是应用程序可以正确引用该库中的全局符号,需要制作一个包含该静态库中全局符号声明的头文件,这个头文件可以包含在应用程序的头文件中,这样就可以使用静态库中的全局符号了。

#include <stdio.h>
#include "static_lib.h"

int main(void)
{
  int a, b;
  printf("please input a and b\n");
  scanf("%d %d", &a, &b);
  printf("the add : %d\n", add(a, b));
  printf("the sub : %d\n", sub(a, b));
  printf("the mul : %d\n", mul(a, b));
  printf("the div : %d\n", div(a, b));
  return 0;
}

使用-l选项来指定静态库,-L参数来指定库文件的搜索路径。-l和-L之后都栉jie风沐雨带参数而不跟空格,所以用一下命令编译:

gcc -L/home/daowm/WorkSpace/C/linux/ch7 static_main.c -lstatic_lib -o static_main

或者使用 "." 表示当前目录:

gcc -L. static_main.c -lstatic_lib -o static_main

注意:-l是链接器选项,一定要放在被编译的源文件之后,即上面的static_main.c之后,若放在前面则会链接失败。

gcc也支持使用-static选项对静态库链接:

gcc static_main.c -static ./libstatic_lib.a -o static_main

以上三种方法都可以。

运行程序如下:

二、动态库

1.动态库的概念

动态库又称为共享库或者动态链接库,现代程序中大量地使用动态链接库,如windows下的dll文件和linux下的so文件,动态库是在程序启动时被装载的。

当一个引用程序装载了一个动态库后,其他应用程序仍可以装载同一个动态库,这个被多个进程同时使用的动态库在内存中只有一个副本。动态库的优点很多:

  • 是代码
  • 便于程序发布
  • 易于模块更新,更新库并不影响程序使用旧的版本
  • 在执行特定程序时,可以覆盖整个库或者更新库中的特定函数

2.创建动态库

这里使用上面的代码来演示

(1)四则运算代码

//static_lib.c
/* 计算加法的函数 */
int add(int a, int b)
{
  return a + b;
}

/* 计算减法的运算 */
int sub(int a, int b)
{
  return a - b;
}

/* 计算乘法的运算 */
int mul(int a, int b)
{
  return a * b;
}

/* 计算除法的运算 */
int div(int a, int b)
{
  return a / b; 
}

(2)Linux下使用gcc创建一个动态库。由于动态库可以被多个进程共享加载,所以需要生成位置无关的目标文件。这时需要使用gcc编译器的-fPIC选项,该选项用于生成位置无关的代码。除了需要使用-fPIC选项外,还需要使用-shared选项,该选项将位置无关的代码制作为动态库。

gcc -shared -fPIC -o shared_lib.so static_lib.c 

这时一个新的动态库就创建成功了。之后用户可以在自己的应用程序中引用该库中的函数,在程序加载的时候链接该库就可以了。

3.使用动态库

动态库创建成功后,应用程序可以引用该库中的函数或者全局变量。同样在.h文件包含该动态库中的全局符号:

//shared_lib.h

extern int add(int a, int b);  //加法函数的声明
extern int sub(int a, int b);  //减法函数的声明
extern int mul(int a, int b);  //乘法函数的声明
extern int div(int a, int b);  //除法函数的声明

编写程序:

//shared_main.c

#include <stdio.h>
#include "shared_lib.h"

int main(void)
{
  int a, b;
  printf("please input a and b\n");
  scanf("%d %d", &a, &b);
  printf("the add : %d\n", add(a, b));
  printf("the sub : %d\n", sub(a, b));
  printf("the mul : %d\n", mul(a, b));
  printf("the div : %d\n", div(a, b));
  return 0;
}

使用动态库编译生成可执行程序:

gcc shared_main.c ./shared_lib.so -o shared_main

运行结果同上。

同时,另外一个程序也可以使用该动态库,因为动态库是共享的。

 

展开阅读全文
打赏
0
2 收藏
分享
加载中
更多评论
打赏
0 评论
2 收藏
0
分享
返回顶部
顶部