Linux 动、静态库的实现

前言:当我们写了一段代码实现了一个方法,如果我们不想把方法的实现过程暴露给别人看,可以把代码打包成一个库,其中形成后缀为.a的是静态库,后缀为.so的为动态库;当别人想使用你的方法时,把打包好的库跟头文件一起扔给他就行。

一、静态库
1.1生成一个简单的静态库

①首先创建两个文件,一个.c方法的实现,一个.h方法的声明;

②简单实现一下

cpp 复制代码
//mymath.h文件 
#pragma once 
 int add(int x,int y);
 int sub(int x,int y);      
cpp 复制代码
//mymath.c文件
  1 #include "mymath.h"  
  2 int add(int x,int y)  
  3 {  
  4   return x+y;  
  5 }  
  6 int sub(int x,int y)  
  7 {  
  8   return x-y;  
  9 }  

③makefile怎么写?

首先要把所有.c文件生成.o文件,然后把.o文件打包生成库(如果是静态库就是.a;如果是动态库就是.o)

cpp 复制代码
//makefile文件
  1 lib=libmymath.a  
  2 $(lib):mymath.o                       
  3   ar -rc $@ $^ ## ar :生成静态库命令;  rc:把所有.o文件打包生成.a文件,如果.a里面已存在则覆盖;  $@ :依赖目标 $^:依赖文件;
  4 mymath.o:mymath.c
  5   gcc -c mymath.c  ##-c 默认生成.o文件
  6 .PHONY:clean    ##清理
  7 clean:
  8   rm -rf *.o *.a mylib 
 10 .PHONY:output      ##库发布                                                                                                                      
 11 output:                                      
 12   mkdir -p mylib/lib  #创建一串路径        
 13   mkdir -p mylib/include 
 14   cp *.h mylib/include  #把头文件拷贝到include
 15   cp *.a mylib/lib    #把.a 库文件拷贝到lib
~

④make一下

当前目录下已写好.c .h和makefile文件:

make后可以看到生成了mymath的.o文件,然后由.o文件生成静态库 libmymath.a:

⑤发布一下

查看一下当前目录:

可以看到生成的mylib文件就是我们制作的库文件,查看里面的内容:

可以看到其中include文件中包含了方法的头文件,lib文件中包含的就是静态库文件!

既然生成好了就来使用以下吧!

1.2 静态库的使用

①创建一个test文件然后把mylib文件拿过来用

②创建一个.c文件里面包含main函数来使用这个库

cpp 复制代码
//main.c文件
1 #include "mymath.h"
2 int main()
3 {
4   printf("1+1= %d\n",add(1,1));                                                                                                                     
5   return 0;
6 }
  ~

③静态库的编译链接

注意:库的编译链接:gcc + 带main函数的.c文件 + -I + 头文件所在的目录 + -L + 库所在的目录 + -l跟库真实的名字(去掉前缀去掉后缀)

编译后查看当前目录:

运行:

这样就成功的完成了静态库的制作到使用!接下来我们来实现下动态库吧!

二、动态库

2.1 生成一个简单的动态库

我们回到lesson16,然后makeclean,然后再创建两个.c文件分别存放两个方法,和其对应的.h方法使用声明(这两个方法用来生成动态库)

随便实现一下这两个方法(主要为了展示动态库的生成和使用):

cpp 复制代码
//mylog.h文件
  1 #pragma once 
  2 void log(char* message);  
cpp 复制代码
//mylog.c文件
    1 #include "mylog.h"
    2 void log(char* message)
    3 {
    4   printf("%s\n",message);                                                                                                                      
    5 }
cpp 复制代码
//myprint.h文件
  1 #pragma once 
  2 void print();   
cpp 复制代码
//myprint.c文件
  1 #include "myprint.h"
  2 void print()
  3 {
  4   printf("hello linux!!!\n");                                                                                                                    
  5 }                                                         
2.2 makefile怎么写

首先makefile 一次生成两个库,一个静态库、一个动态库,生成之后发布为mylib(动、静态库、头文件都在里面):

cpp 复制代码
//makefile文件
  1 static_lib=libmymath.a ##静态库
  2 dynamic_lib=libmymethod.so  ##静态库
  3 .PHONY:all
  4 all:$(static_lib) $(dynamic_lib)
  5 $(static_lib):mymath.o
  6   ar -rc $@ $^ ## ar :生成静态库命令;  rc:把所有.o文件打包生成.a文件,如果.a里面已存在则覆盖;  $@ :依赖目标 $^:依赖文件;
  7 mymath.o:mymath.c
  8   gcc -c mymath.c  ##-c 默认生成.o文件
  9 
 10 $(dynamic_lib):myprint.o mylog.o
 11   gcc -shared -o $@ $^   ##shared: 生成动态库
 12 myprint.o:myprint.c
 13   gcc -fPIC -c $^  ##fpic  :产生位置无关码
 14 mylog.o:mylog.c
 15   gcc -fPIC -c $^
 16 .PHONY:clean    ##清理
 17 clean:
 18   rm -rf *.o *.a mylib *.so 
 19 .PHONY:output      ##库发布
 20 output:                                                                                                                                          
 21   mkdir -p mylib/lib  #创建一串路径
 22   mkdir -p mylib/include 
 23   cp *.h mylib/include  #把头文件拷贝到include
 24   cp *.a mylib/lib    #把.a 库文件拷贝到lib
 25   cp *.so mylib/lib 

make一下:

mymath生成的静态库libmumatg.a ; mylog和myprint生成的libmymethod.so动态库;

发布一下:

拿到test文件夹里用一下:

2.3 动态库的使用

创建一个main函数调用它:

cpp 复制代码
//main.c文件
1 #include "mylog.h"
2 #include "myprint.h"
3 #include "mymath.h"
4 #include <stdio.h>
5 int main()
6 {
7   printf("1-1=%d\n",sub(1,1));
8   log("hello linux!!!\n");
9   print();
10   print();                                                                                                                                     
11   return 0;
12 }

编译链接:

运行:

报错因为加载的时候找不到动态库,解决方法:

①、把库拷贝到系统默认的路径下 /lib64/usr/lib64/

②、在系统文件下创建软连接 /lib64/usr/lib64/

③、LD-LIBRARY_PATH 导入环境变量

④、进入/etc/ld.so.conf.d创建.conf文件并把库路径加进去,然后重新加载 ldconfig

这里我随便用一个,导入环境变量的方法:

导入前:

导入后:

再运行:

动态库使用成功!!

三、动态库如何实现?

相关推荐
艾醒3 分钟前
探索大语言模型(LLM):循环神经网络的深度解析与实战(RNN、LSTM 与 GRU)
算法
艾醒6 分钟前
探索大语言模型(LLM):马尔可夫链——从诗歌分析到人工智能的数学工具
深度学习·算法
sunbyte6 分钟前
Three.js + React 实战系列-3D 个人主页 :完成 Navbar 导航栏组件
开发语言·javascript·react.js
小oo呆7 分钟前
【自然语言处理与大模型】Linux环境下Ollama下载太慢了该怎么处理?
linux·服务器·人工智能
CoovallyAIHub7 分钟前
YOLO版本迷信终结!11领域398万实例实测:告诉你的场景该用哪个版本?
opencv·算法·计算机视觉
诺亚凹凸曼9 分钟前
Java基础系列-LinkedList源码解析
java·开发语言
三原10 分钟前
实现多选树形组件,我把递归用明白了
前端·数据结构·vue.js
葵花日记10 分钟前
数据结构——栈
数据结构
FAREWELL0007512 分钟前
C#进阶学习(八)常见的泛型数据结构类(3)SortedDictionary<TKey, TValue>与SortedList<TKey, TValue>
数据结构·学习·c#·sorteddictioary·sortedlist
海底火旺12 分钟前
两种思路的碰撞:从超时分层法到高效双指针的蜕变
前端·javascript·算法