Top

CSDUNIXC01 DAY03

  1. 静态库的构建和使用
  2. 共享库的构建和使用

1 静态库的构建和使用

1.1 问题

静态库的本质就是将多个目标文件打包成一个文件。在使用时链接静态库就是将库中被调用的代码复制到调用模块中。优点是使用静态库的代码在运行时无需依赖库,且执行效率高,缺点是静态库占用空间大,库中代码一旦修改必须重新链接。

1.2 步骤

实现此案例需要按照如下步骤进行。

步骤一:构建静态库

文件math.h代码如下所示:

#ifndef math_h
#define math_h

double add(double x, double y);
void show(double result);

#endif

文件calc.c代码如下所示:

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

double add(double x, double y)
{
	return x + y;
}

文件calc.c代码如下所示:

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

void show(double result)
{
	printf("%lf\n", result);
}

使用如下命令,将C源文件编译成目标文件:

gcc –c calc.c

gcc –c show.c

使用如下命令,将目标文件打包成静态库文件

ar –r libmath.a calc.o show.o

步骤二:使用静态库

文件main.c代码如下所示:

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

int main()
{
	printf("5.3 + 2.8 = ");
	show(add(5.3, 2.8));

	return0;
}

使用如下命令,与静态库文件一同生成可执行文件:

gcc main.c libmath.a

也可以使用如下命令,先指定静态库文件的路径,再生成可执行文件:

export LIBRARY_PATH=静态库文件所在路径

gcc main.c –lmath //选项-l用于指定静态库名

还可以使用如下命令,生成可执行文件:

gcc main.c –lmath –L静态库文件所在路径

1.3 完整代码

本案例中的完整代码如下所示:

文件math.h代码如下所示:

#ifndef math_h
#define math_h

double add(double x, double y);
void show(double result);

#endif

文件calc.c代码如下所示:

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

double add(double x, double y)
{
	return x + y;
}

文件calc.c代码如下所示:

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

void show(double result)
{
	printf("%lf\n", result);
}

文件main.c代码如下所示:

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

int main()
{
	printf("5.3 + 2.8 = ");
	show(add(5.3, 2.8));

	return0;
}

2 共享库的构建和使用

2.1 问题

共享库和静态库最大的不同就是,链接共享库并不需要将库中被调用的代码复制到调用模块中,相反被嵌入到调用模块中的仅仅是被调用代码在共享库中的相对地址。如果共享库中的代码同时为多个进程所用,共享库的实例在整个内存空间中仅需一份,这正是共享的意义所在,共享库的优点是占用空间小,即使修改了库中的代码,只要接口保持不变,无需重新链接,缺点是使用共享库的代码在运行时需要依赖库,执行效率略低。

2.2 步骤

实现此案例需要按照如下步骤进行。

步骤一:共享库的构建

文件math.h代码如下所示:

#ifndef math_h
#define math_h

double add(double x, double y);
void show(double result);

#endif

文件calc.c代码如下所示:

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

double add(double x, double y)
{
	return x + y;
}

文件calc.c代码如下所示:

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

void show(double result)
{
	printf("%lf\n", result);
}

使用如下命令,将C源文件编译成目标文件:

gcc –c –fpic calc.c

gcc –c –fpic show.c //选项fpic是指生成位置无关代码,即调用代码通过相对地址标识被调用代码的位置,模块中的指令与该模块被加载到内存中的位置无关。

使用如下命令,将目标文件打包成共享库文件

gcc –shared calc.o show.o –o libmath.so

编译和链接也可以合并为一步完成

gcc -shared -fpic calc.c show.c -o libmath.so

步骤二:共享库的使用

文件main.c代码如下所示:

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

int main()
{
	printf("5.3 + 2.8 = ");
	show(add(5.3, 2.8));

	return0;
}

使用如下命令,与共享库文件一同生成可执行文件:

gcc main.c libmath.so

也可以使用如下命令,先指定共享库文件的路径,再生成可执行文件:

export LIBRARY_PATH=共享库文件所在路径

gcc main.c –lmath //选项-l用于指定共享库名

还可以使用如下命令,生成可执行文件:

gcc main.c –lmath –L共享库文件所在路径

运行时需要保证LD_LIBRARY_PATH环境变量中包含共享库所在的路径,可使用以下控制台命令设置

$ export LD_LIBRARY_PATH=共享库文件所在路径

2.3 完整代码

本案例中的完整代码如下所示:

文件math.h代码如下所示:

#ifndef math_h
#define math_h

double add(double x, double y);
void show(double result);

#endif

文件calc.c代码如下所示:

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

double add(double x, double y)
{
	return x + y;
}

文件calc.c代码如下所示:

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

void show(double result)
{
	printf("%lf\n", result);
}

文件main.c代码如下所示:

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

int main()
{
	printf("5.3 + 2.8 = ");
	show(add(5.3, 2.8));

	return0;
}