IE盒子

搜索
查看: 105|回复: 0

C语言动态链接库的搭建和使用

[复制链接]

4

主题

8

帖子

17

积分

新手上路

Rank: 1

积分
17
发表于 2023-4-10 10:03:38 | 显示全部楼层 |阅读模式
1. 概述
在c语言的实际编程中,我们可以把完成某项功能的函数放在一个动态链接库里,然后提供给其他程序调用。
1.1 动态库
动态库是一种不可执行的二进制程序文件,它允许程序共享执行特殊任务所必需的代码和其他资源。Windows平台上动态链接库的后缀名是”.dll”,Linux平台上的后缀名是“.so”。Linux上动态库一般是libxxx.so;相对于静态函数库,动态函数库在编译的时候并没有被编译进目标代码中,你的程序执行到相关函数时才调用该函数库里的相应函数,因此动态函数库所产生的可执行文件比较小。由于函数库没有被整合进你的程序,而是程序运行时动态的申请并调用,所以程序的运行环境中必须提供相应的库。动态函数库的改变并不影响你的程序,所以动态函数库的升级比较方便。
1.2 动态链接库的优点
复用性:DLL的编制与具体的编程语言以及编译器无关,不同语言编写的程序只要按照函数调用约定就可以调用同一个DLL函数
可扩展性:DLL文件与EXE文件独立,只要接口不变,升级程序只需更新DLL文件不需要重新编译应用程序
节省内存:如果多个应用程序使用同一个dll,该dll的页面只需要存入内存一次,所有的应用程序都可以共享它的页面,从而节省内存
2. 生成动态链接库
仅对windows系统进行描述,下面以vs编译器为例:
在创建新项目中选择“动态链接库”
项目的命名就是最后dll的名字,新建h和cpp文件
main.cpp
#include "main.h"
#include <stdio.h>
/* 输入年月日计算一年中第几天 */
int Day_of_year(int year, int month, int day)
{
   int sum,leap;
   switch(month) // 先计算某月以前月份的总天数
   {
       case 1:sum=0;break;
       case 2:sum=31;break;
       case 3:sum=59;break;
       case 4:sum=90;break;
       case 5:sum=120;break;
       case 6:sum=151;break;
       case 7:sum=181;break;
       case 8:sum=212;break;
       case 9:sum=243;break;
       case 10:sum=273;break;
       case 11:sum=304;break;
       case 12:sum=334;break;
       default:printf("data error");break;
   }
   sum=sum+day; // 再加上某天的天数
   if(year%400==0||(year%4==0&&year%100!=0)) {// 判断是不是闰年
       leap=1;
   } else {
      leap=0;
   }
   if(leap==1&&month>2) { // *如果是闰年且月份大于2,总天数应该加一天
       sum++;
   }
   return sum;
}
Main.h
#ifndef __MAIN_H__
#define __MAIN_H__
#include <windows.h>
#ifdef __cplusplus
#define EXPORT extern "C" __declspec (dllexport)
#else
#define EXPORT __declspec (dllexport)
#endif // __cplusplus
EXPORT int Day_of_year(int year, int month, int day);
#endif // __MAIN_H__
编译成功后在bin\Debug目录下生成3个文件:dll.dll,libdll.a,libdll.def
3. 调用动态链接库
新建工程,把dll.dll拷贝到新工程的bin\Debug目录下
main.c
#include <stdio.h>
#include <windows.h>
typedef int(*Getday)(int, int, int); //定义函数类型
HINSTANCE hDll; //DLL句柄
Getday getday;
int main()
{
    hDll = LoadLibrary("dll.dll"); //加载 dll
    getday = (Getday)GetProcAddress(hDll, "Day_of_year");//通过指针获取函数方法
    printf("day = %d\n",  getday(2015, 10, 1) );//调用函数
    FreeLibrary(hDll);//释放Dll句柄
    system("pause");
    return 0;
}
编译就可以使用,当dll程序升级时,只需要替换dll,而不用重新编译exe
4. 调试案例
1)错误一
/tmp/ccMpgzNu.o: In function `main':
test.c:(.text+0x13): undefined reference to `dlopen'
test.c:(.text+0x1c): undefined reference to `dlerror'
test.c:(.text+0x53): undefined reference to `dlsym'
test.c:(.text+0x63): undefined reference to `dlerror'
test.c:(.text+0x89): undefined reference to `dlclose'
test.c:(.text+0xc7): undefined reference to `dlclose'
collect2: error: ld returned 1 exit status
解决方案:
头文件添加:#include <dlfcn.h>
编译选项加上- ldl,即 gcc -o test test.c -ldl ,网上有gcc -ldl -o test test.c,这种方式也是会报这个错误的
2)错误二
error while loading shared libraries: libtiger.so: cannot open shared object file: No such file or direct
我的这段代码里则会打印Load lib.so failed!
解决方案:
在程序代码里配置路径void *pdlHandle = dlopen(“libday.so”, RTLD_LAZY);
将动态链接库配上路径,如 ./libday.so表示可执行文件与链接库同一路径
将动态链接库的目录放到程序搜索路径中,可以将库的路径加到环境变量
export LD_LIBRARY_PATH=pwd:$LD_LIBRARY_PATH(pwd带反撇号的哈)
拷贝libday.so到绝对目录 /lib
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表