Linux C:库的相关概念及简单制作

1. 分文件编程:

在玩stc51单片机、stm32的时候为了主程序的代码简洁,我们经常会使用分文件编程的方法。在Linux C中同样可以使用分文件编程的方法让程序的逻辑更加清晰。

这是一个简单的多函数调用的实例:

#include <stdio.h>

void input2nums(int *x, int *y)
{
	printf("please in put 2 int-numbers\n");
	scanf("%d %d",x, y);
}

int plus(int x, int y)
{
	return (x+y);
}

int minus(int x, int y)
{
	return (x-y);
}
int multipy(int x, int y)
{
	return (x*y);
}

float divide(int x, int y)
{
	return ((float)x/y);
}

int main()
{
	int a;
	int b;
	
	input2nums(&a, &b);
	int sum   = plus(a, b);
	int diff  = minus(a, b);
	int mul   = multipy(a, b);
	float div = divide(a, b);
	
	printf("sum:  %6d\n", sum);
	printf("diff: %6d\n", diff);
	printf("mul:  %6d\n", mul);
	printf("div:  %6.4f\n", div);
	
	return 0;
}

看着比较长,我们可以把它分解成两个文件使代码看起来更直观。

我们把它分成:calcu.c, func.c和func.h

calcu.c:

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

int main()
{
        int a;
        int b;

        input2nums(&a, &b);
        int sum   = plus(a, b);
        int diff  = minus(a, b);
        int mul   = multipy(a, b);
        float div = divide(a, b);

        printf("sum:  %6d\n", sum);
        printf("diff: %6d\n", diff);
        printf("mul:  %6d\n", mul);
        printf("div:  %6.4f\n", div);

        return 0;
}

func.c:

#include <stdio.h>

void input2nums(int *x, int *y)
{
    printf("please in put 2 int-numbers\n");
    scanf("%d %d",x, y);
}

int plus(int x, int y)
{
    return (x+y);
}

int minus(int x, int y)
{
    return (x-y);
}
int multipy(int x, int y)
{
    return (x*y);
}

float divide(int x, int y)
{
    return ((float)x/y);
}

func.h:

#ifndef __FUNC_H
#define __FUNC_H

void input2nums(int *x, int *y);
int plus(int x, int y);
int minus(int x, int y);
int multipy(int x, int y);
float divide(int x, int y);

#endif

在calcu.c中对于头文件的引用使用了两种方法一种是#include <xxx.h>和include "xxx.h"。

这两种引用方法的不同点在于头文件的默认索引地点不同。<>是默认在环境变量中找,“”是默认在当前工作文件夹中寻找。我们也可以简单理解成:<官方的头文件.h>和"自己编写的头文件.h"。

编译和运行:

2. 库

程序函数库可以使整个程序更加模块化,更容易重新编译,更方便升级。而且可以在一定情况下起到代码保护的功能。

库分为:静态函数库、共享函数库、动态加载函数库。

 静态库

在程序执行前(编译)就加入到目标程序中去了。

优点:运行快,发布程序无需提供静态库,移植方便

缺点:程序大,链接时完整拷贝到可执行文件中,被多次使用就有多份冗余拷贝。更新、部署、发布麻烦。

 动态库

在程序执行时动态(临时)由目标程序去调用。

动态函数库和共享函数库是一个东西(在linux是叫做共享对象库,后缀是.so,在windows上叫做动态加载函数库,后缀是.dll)

 优点:1. 链接时不复制,程序运行时由系统动态加载到内存,供程序调用,系统只加载一次,多个程序可以共用,节省内存。

            2.程序升级简单,因为app里面没有库的源码,升级之后只要库的名字不变,函数名以及参数不变,只是算法做了优化,就能加载成功。

 缺点:运行慢,发布程序依赖于动态库。

3.库的制作

3.1静态库的制作

第一步,生成.o文件

gcc func.c -c

第二步,生成.a文件

ar rcs liblfunc.a func.o

这里liblfunc.a就是库文件(命名规则和下面的动态库基本一致)

3.2动态库的制作

命名规则:libname.so.0.0.1

lib是固定前缀 name是库名 .so是后缀 0.0.1是版本号(版本号可无)

gcc -shared -fpic func.c -o liblfunc.so
-shared #指定生成动态库
-fpic #选项作用于编译阶段,在生成目标文件时使用该选项,以生成位置无关码

4.库的使用

4.1静态库的使用

静态库的使用需要一个主程序(.c文件),一个库的头文件(.h),一个库文件(.a)。

我这里是calcu.c、func.c、liblfunc.a三个文件。

gcc calcu.c -llfunc -L ./ -o proj_static
-l #是链接库 默认路径/usr/local/lib
usage:-llfunc #这里链接到一个名为liblfunc.a的库文件
-L #是指定路径
./ #是当前路径
-o #是命名

4.2动态库的使用 

使用方法和静态库相同。

gcc calcu.c -llfunc -L ./ -o proj_dynamic

 生成proj_dynamic后发现不能运行,报错提示就是说明,使用动态库编译后运行也要链接动态库。

解决办法:

1. 将生成的动态库文件拷到/usr/lib/下

sudo cp liblfunc.so /usr/lib/

2. 应用动态库指定动态库的位置

linux动态库(.so)搜索路径(目录)设置方法_my_angle2016的博客-CSDN博客_linux动态库搜索路径https://blog.csdn.net/my_angle2016/article/details/121770237?ops_request_misc=&request_id=&biz_id=102&utm_term=linux%E5%8A%A8%E6%80%81%E5%BA%93%E6%90%9C%E7%B4%A2%E8%B7%AF%E5%BE%84&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-0-121770237.nonecase&spm=1018.2226.3001.4187把动态库所在的文件夹加到环境变量里面,就可以链接了。

export LD_LIBRARY_PATH="/home/pi/ccode/workshop"

 但是这个办法是临时的,更换终端之后就失效了。

可以写一个shell脚本,将配置环境变量和运行程序一起执行就可以了。

vi start_proj_dynamic.sh
export LD_LIBRARY_PATH="/home/pi/ccode/workshop"

./proj_dynamic
chmod +x start_proj_dynamic.sh

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值