基于linux的程序库文件打包和调用的实现(一)——静态库文件打包和调用

        随着技术的发展,基于linux项目的软件代码越发复杂,原来一个人可以完成的软件项目,现在可能需要多个人合作、多个部门合作、多个企业合作,每个人、每个部门、每个企业可能负责部分软件模块的开发。各个软件模块在调试过程由于涉及企业知识产权、源代码防止修改、安全性等多方面考虑,技术人员会将自己完成的软件生成库文件(含库文件和头文件(.h文件))、接口使用说明供其他模块调用,本文将从通过一个应用程序的例子,介绍linux环境下应用软件库文件的打包和调用过程。

(一)应用软件设计

1.设计一个获取系统时间和设置系统时间功能的软件,获取的时间转换为便于理解的bcd码格式,该软件由systime.c的源文件和systime.h的头文件两部分组成。

systime.c源码如下所示:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <sys/time.h>
#include "systime.h"

/******************************************************************************
*FUNCATION NAME  :	Uint8 dec_to_bcd(Uint8 dec)
*CREATE DATE     :	2023-05-31
*CREATE BY       :	LSL
*FUNCTION        :	十进制转bcd码
*MODIFY DATE     :
*INPUT           :
*OUTPUT          :
*RETURN          :
*OTHERS          :
******************************************************************************/
unsigned char dec_to_bcd(unsigned char dec)
{
	unsigned char temp;
	temp=(dec/10)*16+(dec%10);
	return(temp);
}
/******************************************************************************
*FUNCATION NAME  :	Uint8 bcd_to_dec(Uint8 bcd)
*CREATE DATE     :	2023-05-31
*CREATE BY       :	LSL
*FUNCTION        :	bcd转10进制
*MODIFY DATE     :
*INPUT           :
*OUTPUT          :
*RETURN          :
*OTHERS          :
******************************************************************************/
unsigned char bcd_to_dec(unsigned char bcd)
{
	unsigned char temp;
	temp=(bcd/16)*10+(bcd%16);
	return(temp);
}


/******************************************************************************
*FUNCATION NAME  :	void get_systimer(systimer_t *systimerstruct)
*CREATE DATE     :	2023-05-31
*CREATE BY       :	LSL
*FUNCTION        :	从系统获取时间函数(含年月日时分秒)
*MODIFY DATE     :
*INPUT           :
*OUTPUT          :
*RETURN          :
*OTHERS          :
******************************************************************************/
void get_Systimer(systimer_t *systimerstruct)
{
	unsigned char	date;		//日
	unsigned char	month;		//月
	unsigned int	year;		//年
	
	unsigned char	second;		//秒
	unsigned char	minute;		//分
	unsigned char	hour;		//时
	
	time_t current_time;
	struct tm *now_time;

	time(&current_time);//获得本地时间
	now_time = localtime(&current_time);//转换为tm格式的时间

	year=(now_time->tm_year + 1900);//获得年

	month= (now_time->tm_mon + 1);//获得月

	date=(now_time->tm_mday);//获得天

	hour=(now_time->tm_hour);//获得小时

	minute=(now_time->tm_min);//获得分钟

	second=(now_time->tm_sec);//获得秒

//	printf("the year is %d,the mon is %d,the day is %d,the hour is %d,the min is %d,the sec is %d,the dst is %d!\n",year,month,date,hour,minute,second,(now_time->tm_isdst));

	systimerstruct->uniondate_t.structdate.res1 =dec_to_bcd(year/100);	//BCD转换,获得年 高16位
	systimerstruct->uniondate_t.structdate.year=dec_to_bcd(year%100);	//BCD转换,获得年 低16位
	systimerstruct->uniondate_t.structdate.month=dec_to_bcd(month);	//BCD转换,获得月
	systimerstruct->uniondate_t.structdate.date=dec_to_bcd(date);		//BCD转换,获得天

	systimerstruct->uniontime_t.structtime.res1=dec_to_bcd(0);		//BCD转换
	systimerstruct->uniontime_t.structtime.hour=dec_to_bcd(hour);		//BCD转换,获得小时
	systimerstruct->uniontime_t.structtime.minute=dec_to_bcd(minute);	//BCD转换,获得分
	systimerstruct->uniontime_t.structtime.second=dec_to_bcd(second);	//BCD转换,获得秒
	
}


/******************************************************************************
*FUNCATION NAME  :	void set_systimer(systimer_t *systimerstruct)
*CREATE DATE     :	2023-05-31
*CREATE BY       :	LSL
*FUNCTION        :	向系统写入时间函数(含年月日时分秒)
*MODIFY DATE     :
*INPUT           :
*OUTPUT          :
*RETURN          :
*OTHERS          :
******************************************************************************/
void set_Systimer(systimer_t *systimerstruct)
{
	int ret = 0;

	unsigned char	date;		//日
	unsigned char	month;		//月
	unsigned int	year;		//年
	
	unsigned char	second;		//秒
	unsigned char	minute;		//分
	unsigned char	hour;		//时

	time_t current_time;
	struct tm now_time;
	struct timeval time_tv;

	year=bcd_to_dec(systimerstruct->uniondate_t.structdate.res1)*100;
	year+=bcd_to_dec(systimerstruct->uniondate_t.structdate.year);		//年

	month=bcd_to_dec(systimerstruct->uniondate_t.structdate.month);		//月

	date=bcd_to_dec(systimerstruct->uniondate_t.structdate.date);		//日

	hour=bcd_to_dec(systimerstruct->uniontime_t.structtime.hour);		//时

	minute=bcd_to_dec(systimerstruct->uniontime_t.structtime.minute);	//分

	second=bcd_to_dec(systimerstruct->uniontime_t.structtime.second);	//秒

	now_time.tm_year = (year - 1900);	//年

	now_time.tm_mon = (month - 1);		//月

	now_time.tm_mday = (date);			//天

	now_time.tm_hour = hour;			//时

	now_time.tm_min = minute;			//分

	now_time.tm_sec = second;			//秒

	//now_time.tm_isdst = 0;				//dst时区

	current_time = mktime(&now_time);	//完成时间转换
	
	time_tv.tv_sec = current_time;
	time_tv.tv_usec = 0;

	ret = settimeofday(&time_tv, NULL);		//将时间写给系统
	if(ret != 0)
	{
		printf("settimeofday failed\n"); 
	}
}

systime.h源码如下所示:

#ifndef SRC_SYSTIME_H_
#define SRC_SYSTIME_H_

#pragma pack(1)
typedef struct	systimer
{
	union
	{
		
		struct
		{
			unsigned char	date;		//日
			unsigned char	month;		//月
			unsigned char	year;		//年
			unsigned char	res1;		//年的高16位
		}structdate;
		unsigned	int		day;	//日期
	}uniondate_t;
	union
	{
		
		struct
		{
			unsigned char	second;		//秒
			unsigned char	minute;		//分
			unsigned char	hour;		//时
			unsigned char	res1;		//预留
		}structtime;
		unsigned	int		time;	//时间
	}uniontime_t;
}systimer_t;
#pragma pack(push)

void get_Systimer(systimer_t *systimerstruct);//获得系统时间
void set_Systimer(systimer_t *systimerstruct);//设置系统时间

#endif

2.其中源文件systime.c实现获取、设置系统时间,并转换systime.h定义的系统时间格式。

(二)静态库打包

1.新建static_lib的文件夹,并将上述systime.c和systime.h两个文件拷贝到static_lib目录,如下所示:

图1 新建静态库目录

 

2.为了提高编译打包方法的移植性,在静态库目录中新建Makefile文件,内容如下所示:

图2 新建Makefile文件

 

3.运行make指令,生成libapp_systimer.a的静态库文件,如下图所示。

图3 生成软件的静态库文件libapp_systimer.a

 

4.以上生成的libapp_systimer.a文件和systim.h文件,供后续静态库调用。

(三)静态库调用测试

1.新建测试目录static_test,并在static_test目录下新建libsystime的子文件夹,并拷贝上节生成的静态库文件libapp_systimer.a和头文件systime.h到静态库测试目录的系统时间库子目录static_test/libsystime。具体流程如下所示:

图4 新建测试目录,并拷贝库文件到库文件目录

 

2.在测试目录static_test中,新建测试程序main.c,获取系统时间,并打印输出:

图5 引用头文件,获得时间,并打印输出

 

3.新建Makefile文件,注意:包含头文件和lib库的路径,如下图所示:

图6 Makefile文件内容

 

4.新建编译脚本build.sh,编译脚本内容如下所示:

图7 新建编译脚本

 

5.给编译脚本添加可执行权限,并运行编译脚本,编译生成测试软件的可执行程序myapp,如下图所示:

图8 编译生成可执行程序

 

6.运行可执行程序,获得当前时间,如下图所示,说明静态库的调用成功。

图9 测试程序调用静态库成功

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
### 回答1: 在Linux中,可以使用动态链接(.so文件)来实现代码的共享和重用。要调用动态,需要使用以下步骤: 1. 将动态文件放置在系统的标准路径中,例如/usr/lib或/usr/local/lib。 2. 在程序中使用#include指令包含动态的头文件。 3. 在编译时使用-l选项指定要链接的动态,例如gcc -o myprogram myprogram.c -lmylibrary。 4. 在程序中使用动态中定义的函数或变量。 需要注意的是,动态文件的名称应该以lib开头,并以.so结尾,例如libmylibrary.so。此外,动态文件应该与程序的架构(例如32位或64位)相匹配。 ### 回答2: Linux是一个开源的操作系统,具有良好的扩展性和定制性,其中调用动态so文件是一个非常重要的功能。 动态是一个共享,它在程序的运行期间被载入到内存中。与静态不同,动态可以在程序产生更新时,达到较小的更新体积。这种更新方式可以大大降低程序的升级和维护的成本,同时也能够提高程序的运行效率。 在Linux系统中,调用动态so文件可以通过三个步骤实现。首先,需要加载动态,这可以通过将so文件加入到LD_LIBRARY_PATH中来实现。其次,需要在程序中引用动态,这通常是通过编写C代码来实现的。最后,还需要将动态链接到程序中,以便程序能够正常运行。 在使用动态的过程中,需要注意一些常见的问题。例如,如果调用的动态不存在,或者没有正确设置LD_LIBRARY_PATH,那么程序就会出现错误。此外,在不同版本的Linux系统上,动态的版本也可能会发生变化,这可能会影响程序的正常运行。因此,在使用动态时,开发人员需要非常谨慎,并确保正确地处理任何可能导致程序出错的问题。 总之,调用动态so文件Linux开发中的一个重要功能。合理使用动态可以提高程序的效率,同时也可以降低程序的维护和更新成本,这对于企业和开发者来说都是非常重要的。 ### 回答3: 动态(Dynamic Link Library,简称 DLL)是一种常见的软件形式,其主要作用是在程序运行时,通过动态加载,提供程序所需的功能。在Linux中,动态通常被称为共享对象(Shared Object,简称SO),其扩展名为.so。 在Linux系统中,程序调用动态有两种方式:静态链接和动态链接。 静态链接是将所有依赖的代码都复制到可执行文件中,使得程序独立运行。这种方式的缺点是,可执行文件体积较大,不利于程序的可维护性。因此,在Linux系统中常用的方式是动态链接。 动态链接是将程序和其所依赖的进行分离,使得程序只加载所需的代码,从而节省了内存空间,并且方便了程序的更新和维护。在Linux中,程序动态链接的方式是通过ld.so动态链接器实现的。 下面是在Linux系统中调用动态.so文件的基本步骤: 1. 编译动态文件。编译动态文件需要使用-fPIC选项,例如: gcc -fPIC -shared -o libtest.so test.c 编译完成后,会生成一个名为libtest.so的动态文件。 2. 在程序中加载动态。 在程序中调用动态需要使用到LD_LIBRARY_PATH环境变量,其作用是告诉系统动态文件的搜索路径,例如: export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib 然后,通过调用dlopen函数加载动态,例如: void* handle = dlopen("libtest.so", RTLD_NOW); 3. 使用动态中的函数。 动态中的函数可以通过dlsym函数动态加载,例如: void (*func)() = (void (*)())dlsym(handle, "test_func"); (*func)(); 4. 卸载动态。 在程序使用完动态后,需要调用dlclose函数将其卸载,例如: dlclose(handle); 总结:Linux调用动态.so文件需要先编译动态文件,然后在程序中加载动态并使用其中的函数,最后卸载动态

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

少林and叔叔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值