当前位置: 首页 > news >正文

C语言调用so/dll动态库

文章目录

  • windows系统
  • linux系统
  • windows 与 linux下 C 调用动态库的差异

C语言调用动态链接库

windows系统

windows系统下,C语言调用win下的动态库dll,使用头文件<windows.h>。

  • 准备基础C代码 lauf.c

#include <stdio.h>// 定义函数,并发布到 共享库dll
int lauf(char* ptr) {printf("%s-%s\n", __FILE__, ptr);return 0;
}
  • 编译共享库 lauf.dll
# 编译为共享库
gcc ./lauf.c -fPIC -shared -o lauf.dll# 查看lauf.dll中的symbol
strings lauf.dll | findstr lauf
# 使用objdump查看
objdump -p lauf.dll | findstr lauf
  • 编写调用动态库的C代码 main.c
#include <stdio.h>
#include <windows.h>int main() {// 加载动态库HINSTANCE winDll;winDll = LoadLibrary(TEXT("lauf.dll"));if (winDll == NULL) {printf("加载dll失败\n");return 1;}// 获取winDll 中的符号(函数或者变量)// 不确定函数的返回类型、参数类型时,自定义函数指针typedef int (*MyFunc)(char*); // 自定义 函数指针 类型,使用该类型声明变量MyFunc func;// 定位符号func = (MyFunc)GetProcAddress(winDll, "lauf");if (func == NULL) {printf("获取符号失败\n");return 1;}// 调用函数char* name = "main-jack";int result = func(name); // 返回整型printf("函数调用结果:%d\n", result);return 0;}
  • 编译 main.c 成为 main.exe
# 编译
gcc ./main.c -o main.exe -L. -l lauf
# -L 指定加载的动态链接库的 路径,如 -L . 从当前目录加载
# -l 指定使用的动态链接库名,如-l lauf,注意不带dll扩展名 
# 至少指定一个L,或者两者同时指定,如 -L . -l lauf# -I 指定使用的 头文件路径# g++ 编译C++ 方式类似

调用main.exe 输出结果:
在这里插入图片描述

 

linux系统

C语言调用linux下的动态库so,使用头文件<dlfcn.h>,下面以CentOS为例说明。

  • 准备C代码,并编译为so
    在这里插入图片描述

base.c


#include <stdio.h>int funcBase(){printf("func base is running...");return 10;
}

lauf.c

#include <stdio.h>// 定义变量
char *username = "jack";
char *funcLauf(char* ptr){printf("%s-username:%s\n", __FILE__, ptr);return ptr;}

main.c

#include <stdio.h>// declare func defined in other c source.
extern int funcBase();
extern char* funcLauf(char* ptr);// declare global variable
extern char* username;// 入口函数
int main(){int result = funcBase();printf("%s-result:%d\n", __FILE__, result);char* name = funcLauf(username);printf("%s-name: %s\n", __FILE__, name);return 0;
}

 
编译可执行程序:

# 命令行下编译,指定需要编译的所有C源文件,其他目录下的也可以指定
gcc ./*.c -o app.out# 编译为动态共享库
gcc -fPIC ./*.c -shared -o app.so

图中的app.out 是在linux下编译的可执行程序, ./app.out 即可执行

 

  • 编写C代码,调用上一步的so(共享库、动态库);
    • 使用头文件 < d l f c n . h > <dlfcn.h> <dlfcn.h>仅linux环境下用
      • void *dlopen(const char *filename, int flag),打开一个动态库;如dlopen(“xxx.so”, RTLD_LAZY)
      • void *dlsym(void *handle, const char *symbolName),获取动态库中的函数/变量(符号);如dlsym(ptr, “func”)
      • int dlclose(void *handle),关闭一个动态库;
      • char *dlerror(void): 返回上一个动态链接库错误的字符串描述。
    • 使用 LD_PRELOAD 环境变量
    • 使用 -l 编译器选项链接库文件
// 这里用 <dlfcn.h> 使用动态库的头文件方式
#include <stdio.h>
#include <dlfcn.h> // 使用动态库的头文件int main() {void *handle = NULL;char* (*func)(char*); // ptr of funcchar *error = NULL;char* username = "jack";// load libhandle = dlopen("app.so", RTLD_LAZY); // lazy loadif (!handle) {fprintf(stderr, "%s\n", dlerror()); // 错误信息输入到dlerrorreturn 1;}// get func inner sofunc = dlsym(handle, "funcLauf");if ((error = dlerror()) != NULL)  { // 有错误输出fprintf(stderr, "%s\n", error);return 1;}// 函数调用printf("Result: %s\n", func(username));// close so ptrdlclose(handle);return 0;
}

编译可执行文件:

# compile 
gcc moduleCallSo.c -o moduleCallSo.out -ldl
# gcc, compiler
# moduleCallSo.c, C source file
# -o, output to a file
# -l, to include dynamic lib, 'dl' is dynamic linked lib

执行结果:
在这里插入图片描述

 

windows 与 linux下 C 调用动态库的差异

在这里插入图片描述

相关文章:

  • JAVA代码审计之SQL注入代码审计
  • 【面试宝藏】Redis 常见面试题解析其二
  • CAD2022下载与安装
  • 医学领域科技查新点提炼方法!---附案例分析
  • 合并两个排序链表
  • 【Python】已完美解决:(Python键盘中断报错问题) KeyboardInterrupt
  • uniapp自定义的下面导航
  • 基于Python的AI动物识别技术研究
  • 酷开科技丨酷开系统重塑家庭娱乐生态,开启家庭生活新体验
  • RAG系统进阶(五)文本分割优化技巧及代码
  • Spring学习笔记
  • Linux基础IO【II】
  • RuoyiAdmin项目搭建及Docker 部署备忘
  • 【FreeRTOS】创建第一个多任务程序
  • Polar Web【简单】upload
  • 收藏网友的 源程序下载网
  • 【RocksDB】TransactionDB源码分析
  • angular组件开发
  • Asm.js的简单介绍
  • LeetCode刷题——29. Divide Two Integers(Part 1靠自己)
  • Mac转Windows的拯救指南
  • php的插入排序,通过双层for循环
  • Python爬虫--- 1.3 BS4库的解析器
  • Python中eval与exec的使用及区别
  • spring学习第二天
  • Terraform入门 - 1. 安装Terraform
  • text-decoration与color属性
  • 给Prometheus造假数据的方法
  • 技术胖1-4季视频复习— (看视频笔记)
  • 你真的知道 == 和 equals 的区别吗?
  • 如何设计一个微型分布式架构?
  • 首页查询功能的一次实现过程
  • 数据结构java版之冒泡排序及优化
  • 微信小程序:实现悬浮返回和分享按钮
  • 走向全栈之MongoDB的使用
  • 1.Ext JS 建立web开发工程
  • RDS-Mysql 物理备份恢复到本地数据库上
  • 智能情侣枕Pillow Talk,倾听彼此的心跳
  • 资深实践篇 | 基于Kubernetes 1.61的Kubernetes Scheduler 调度详解 ...
  • ​【原创】基于SSM的酒店预约管理系统(酒店管理系统毕业设计)
  • ​一、什么是射频识别?二、射频识别系统组成及工作原理三、射频识别系统分类四、RFID与物联网​
  • #经典论文 异质山坡的物理模型 2 有效导水率
  • (1)安装hadoop之虚拟机准备(配置IP与主机名)
  • (第一天)包装对象、作用域、创建对象
  • (附源码)apringboot计算机专业大学生就业指南 毕业设计061355
  • (附源码)python旅游推荐系统 毕业设计 250623
  • (附源码)ssm经济信息门户网站 毕业设计 141634
  • (论文阅读31/100)Stacked hourglass networks for human pose estimation
  • (原创)攻击方式学习之(4) - 拒绝服务(DOS/DDOS/DRDOS)
  • (原創) 如何解决make kernel时『clock skew detected』的warning? (OS) (Linux)
  • **PHP二维数组遍历时同时赋值
  • .net core 6 集成 elasticsearch 并 使用分词器
  • .NET Core中的去虚
  • .net refrector
  • .net 重复调用webservice_Java RMI 远程调用详解,优劣势说明