gcc生成静态库.a和动态库.so及其实例使用

2023-02-05 07:57:49

一、用gcc生成.a静态库和.so动态库

1、例子1 hello程序讲解

① 创建目录并编辑生成例子程序 hello.h、hello.c 和main.c

(1)例子程序hello.h

#ifndef HELLO_H
#define HELLO_H
void hello(const char *name);
#endif

(2)例子程序 hello.c

#include<stdio.h>
void hello(const char *name)
{
printf("Hello %s\n",name);
}

(3)例子程序 main.c

#include"hello.h"
int main()
{
hello("everyone");
return 0;
}

(4)将hello.c编译成.o文件

gcc -c hello.c

在这里插入图片描述
提示:文件编辑可用 vim、nano、gedit等

②gcc生成静态库并使用

(1) 创建静态库
静态库文件名规范格式:lib为前缀,紧跟静态库名,扩展名为.a。 创建静态库用ar命令。

ar -crv libmyhello.a hello.o

如图所示:
在这里插入图片描述在这里插入图片描述
(2)使用静态库
方法一:gcc -o hello main .c -L -lmyhello

提示:main.c还可以放在-L.和-lmyhello之间,但是不能放在它俩之后,否则myhello没有定义。

-L:表示连接的库在当前目录

如图所示:在这里插入图片描述
方法二:gcc main.c libmyhello.a -o hello
如图所示:
在这里插入图片描述
方法三:先生成 main.c:gcc -c main.c
再生成可执行文件:gcc -o hello main.o libmyhello.a
如图所示:
在这里插入图片描述
(3)查看公用函数是否真的连接到目标文件hello中
如图所示:
在这里插入图片描述
发现在删除静态库后,可执行文件依然执行,表明静态库中的公用函数已经连接到目标文件中了。

③gcc生成动态库并使用

(1)由.o文件创建动态库文件
动态库文件名规范格式:lib前缀,紧跟动态库库文件名,文件扩展名为.so。创建动态库为gcc命令。

gcc -shared -fPIC -o libmyhello.so hello.o

如图所示:
在这里插入图片描述
提示:-shared 该选项指定生成动态连接库(让连接器生成 T 类型的导出符号表,有时候也生成弱连接 W 类型的导出符号),不用该标志外部程序无法连接。相当于一个可执行文件。
-fPIC 表示编译为位置独立的代码,不用此选项的话编译后的代码是位置相关的所以动态载入时是通过代码拷贝的方式来满足不同进程的需要,而不能达到真正代码段共享的目的。
(2)使用动态库

 gcc -o hello main.c -L. 或gcc main.c libmyhello.so -o hello

执行./hello出错,因连接时用的是当前目录的动态库文件,运行时是去/usr/lib中找动态库文件,所以将文件libmyhello.so 复制到目录/usr/lib中。
如图所示:
在这里插入图片描述
发现在程序运行时是需要动态库的。

④当静态库和动态库同名时,gcc的选择

(1)删除所有生成文件,恢复到3个子程序创建完成状态。
在这里插入图片描述

(2)创建静态库文件 libmyhello.a 和动态库文件 libmyhello.so。

gcc -c hello.c
ar -ccr libmyhello.a hello.o 
gcc -shared -fPIC -o libmyhello.so hello.o

在这里插入图片描述
如图所示:
在这里插入图片描述
结果:当静态库和动态库同名时,gcc 命令将优先使用动态库,默认去连/usr/lib 和/lib 等目录中的动态库。

⑤静态库和动态库的总结

静态库:静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库。
动态库:动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入,因此在程序运行时还需要动态库存在。

2、实例2

①创建程序:
A1.c:

#include <stdio.h>
void print1(int arg){
printf("A1 print arg:%d\n",arg);
}

A2.c:

#include <stdio.h>
void print2(char *arg){
printf("A2 printf arg:%s\n", arg);
}

A.h:

#ifndef A_H
#define A_H
void print1(int);
void print2(char *);
#endif

test.c:

#include <stdlib.h>
#include "A.h"
int main(){
print1(1);
print2("test");
return 0;
}

在这里插入图片描述
②静态库.a 文件的生成与使用。
在这里插入图片描述
③共享库.so 文件的生成与使用
在这里插入图片描述

3、 实例3

①创建程序:

sub1.c:

float x2x(int a,int b)
{
	float c=0;
	c=a-b;
	return c;
}

sub2.c:

float x2y(int a,int b)
{
	float c=0;
	c=a*b;
	return c;
}

sub.h

#ifndef SUB_H
#define SUB_H
float x2x(int a,int b);
float x2y(int a,int b);
#endif

main.c:

#include<stdio.h>
#include"sub.h"
void main()
{
	int a,b;
	printf("请输入a:");
	scanf("%d",&a);
	printf("请输入b:");
	scanf("%d",&b);
	printf("a-b=%.2f\n",x2x(a,b));
	printf("a*b=%.2f\n",x2y(a,b));
}

如图所示:
在这里插入图片描述

②生成三个.o文件

gcc  -c sub1.c sub2.c main.c

在这里插入图片描述

③将x2x、x2y目标文件生成静态库并使用

ar crv libsub.a sub1.o sub2.o
gcc -o main main.c libsub.a

在这里插入图片描述

④将x2x、x2y目标文件生成动态库并使用

gcc -shared -fPIC -o libsosub.so sub1.o sub2.o
gcc -o main main.c libsosub.so

在这里插入图片描述

⑤将静态库和动态库生成文件大小比较

静态库大小:
在这里插入图片描述

动态库大小:
在这里插入图片描述
结论:比较发现静态库文件小于动态库文件,生成的可执行文件差别较小。

二、 实验总结

本实验为第二次使用gcc,相比第一次对于ubuntu的操作熟悉了很多。本次实验主要为验证过程,所以操作较为简单,熟悉静态库和动态库的用法及区别。

三、参考资料

[1]Linux下静态库.a与.so库文件的生成与使用。
[2]用gcc生成静态库和动态库。

  • 作者:捶死挣扎的小猴
  • 原文链接:https://blog.csdn.net/m0_48861452/article/details/120651479
    更新时间:2023-02-05 07:57:49