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 调用动态库的差异

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/26590.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

算法课程笔记——线段树维护矩阵

算法课程笔记——线段树维护矩阵 2

前后端知识点汇总

springboot项目启动 springboot集成naocs和redis springboot集成mybatis springboot集成mybatisPlus 集成rabbitMq 集成sa-token satoken介绍 sa-token官网Sa-Token 是一个轻量级 Java 权限认证框架,主要解决:登录认证、权限认证、单点登录、OAuth2.0、分布式Session会…

【stm32】基于I2C协议的OLED显示(利用U82G库)

【stm32】基于I2C协议的OLED显示&#xff08;利用U82G库&#xff09; 一、实验目的二、探究任务三、原理探究3.1 I2C接口3.1.1 概述3.1.2 主要特点3.1.3 功能描述3.1.4 从模式3.1.5 主模式3.1.6 时序协议 3.2 OLED屏3.2.1 工作原理3.2.2 汉字点阵显示原理3.2.3 汉字点阵取模 四…

【后端开发】服务开发场景之高性能(CDN与负载均衡,数据库优化,消息队列)

【后端开发】服务开发场景之高性能&#xff08;CDN与负载均衡&#xff0c;数据库优化&#xff0c;消息队列&#xff09; 文章目录 1、内容分发网络&#xff08;CDN &#xff09; & 负载均衡算法CDN是什么&#xff1f;&#xff08;静态资源加速&#xff09;CDN的应用场景&am…

OV5647与树莓派bullseye 64bit的兼容性问题

OV5647与树莓派bullseye 64bit的兼容性问题 1. 源由2. 问题3. 分析方法一&#xff1a;使用 pyudev 库方法二&#xff1a;使用 v4l2-ctl 工具方法三&#xff1a;直接读取 /dev 目录方法四&#xff1a;使用 OpenCV方法五&#xff1a;使用 Picamera方法六&#xff1a;使用 libcame…

『原型资源』Axure自带图标库不够用,第三方经典图标库来袭

​今天小编为大家带来第三方经典图标库&#xff0c;己确认内容可用现推荐给大家。直接上手就可不用自己画哈~ 获取原型文档请与班主任联系&#xff01; 先睹为快&#xff0c;合适再拿走不谢&#xff1a; 图标太多&#xff0c;截取部分给大家参考o(*&#xffe3;︶&#xffe3;*…

Java最新面试题(全网最全、最细、附答案)

一、Java基础 1、基础概念与常识Java 语言有哪些特点? 简单易学&#xff08;语法简单&#xff0c;上手容易&#xff09;&#xff1b;面向对象&#xff08;封装&#xff0c;继承&#xff0c;多态&#xff09;&#xff1b;平台无关性&#xff08; Java 虚拟机实现平台无关性&a…

OCP学习笔记-007 SQL语言之二:DML

2. DML - Data Manipulation Language 数据操纵语句,用于添加、删除、更新和查询数据库记录,并检查数据完整性,常用的语句关键字主要包括insert、delete、udpate和select等。(增添改查) 事务:A transaction consists of a collection of DML statements that form a logi…

Vue 3获取DOM元素的大小以及相对于视口的位置的getBoundingClientRect属性

在Vue 3中&#xff0c;可以使用ref来获取DOM元素的getBoundingClientRect属性。 如果元素已挂载&#xff0c;我们使用 getBoundingClientRect 方法来获取元素的位置和大小信息。这个方法返回一个对象&#xff0c;其中包含了 left、top、right、bottom 等属性&#xff0c;这些属…

LVS负载均衡集群企业级应用实战-LVS/NAT模式(三)

目录 LVS/NAT模式 一. 环境准备 二. 对虚拟服务器操作 三. 对真实服务器操作 四. 打开网站验证 LVS/NAT模式 一. 环境准备 主机名主机IP模拟服务器系统用途localhost 10.36.178.156 192.168.226.137 虚拟服务器 Rocky_linux 客户兼负载均衡机分发IPlocalhost192.168.226…

关于Linux桌面系统的普及 这里是一些建议

Linux 桌面系统在普及方面面临一些挑战&#xff0c;尽管它在服务器和开发者社区中非常受欢迎。为了提高其普及率&#xff0c;可以从以下几个方面着手&#xff1a; 1. 改善用户体验 用户界面友好性&#xff1a;提升桌面环境的易用性和美观度&#xff0c;使其更符合普通用户的习…

记C#优化接口速度过程

前提摘要 首先这个项目是接手的前一任先写的项目&#xff0c;接手后&#xff0c;要求对项目一些速度相对较慢的接口进行优化&#xff0c;到第一个速度比较慢的接口后&#xff0c;发现单接口耗时4-8秒&#xff0c;是的&#xff0c;请求同一个接口&#xff0c;在参数不变的情况下…

【个人博客搭建】(24)统一api接口返回格式

统一接口的返回格式是为了方便开发的数据对接。 在现如今前后端分离的趋势下&#xff0c;需要对接各种类型的数据 所以&#xff0c;我们需要一个标准的数据格式。 1、定义数据格式&#xff1a;例如下边就是一个常见的格式 {"succeed":true,"code": 200,&q…

【算法——动态规划(从dfs回溯开始推导dp)】

基础理论 递归&#xff1a; 递&#xff1a;大问题分解子问题的过程 &#xff1b; 归&#xff1a;产生答案 dp&#xff1a;只进行归&#xff1b;用已知的最底层的&#xff08;递归的边界&#xff0c;搜索树的底&#xff09;&#xff0c;推出未知 《视频索引》 一句话&…

TDengine数据迁移

前言 taosdump 是一个支持从运行中的 TDengine 集群备份数据并将备份的数据恢复到相同或另一个运行中的 TDengine 集群中的工具应用程序。 taosdump 可以用数据库、超级表或普通表作为逻辑数据单元进行备份&#xff0c;也可以对数据库、超级 表和普通表中指定时间段内的数据记录…

蓝牙BLE上位机工具开发理论线索梳理_5.Windows WinRT API包Microsoft.Windows.SDK.Contracts

1. WinRT API包介绍 本文介绍下Windows WinRT API包&#xff08;Microsoft.Windows.SDK.Contracts&#xff09;&#xff0c; 如图1是SDK包的描述。 图1 Microsoft.Windows.SDK.Contracts Windows WinRT API包使您能够将最新的Windows运行时API支持添加到您的。net Framework 4.…

ArcGIS JSAPI 高级教程 - ArcGIS Maps SDK for JavaScript - 探测效果(地图探测、地图窥探)

ArcGIS JSAPI 高级教程 - ArcGIS Maps SDK for JavaScript - 探测效果&#xff08;地图探测、地图窥探&#xff09; 实现原理 ArcGIS Maps SDK for JavaScript 从 4.29 开始增加 RenderNode 类&#xff0c;可以添加数据以及操作 FBO&#xff08;ManagedFBO&#xff09;&#xf…

媲美Sora,免费使用!带物理模拟的,文生视频模型

6月13日&#xff0c;知名3D建模平台Luma AI发布最新文生视频模型Dream Machine&#xff0c;向所有用户免费开放使用。 Dream Machine除了支持文本之外&#xff0c;还可使用图片作为引导来生成视频&#xff0c;其生成的视频质量、动作一致性、色彩、光影、饱和度、运镜等方面&a…

Mysql学习笔记-进阶篇

一、存储引擎 1、MYSQL体系结构 连接层、服务层、引擎层、存储层&#xff1b; 2、存储引擎简介 存储引擎就是存储数据、建立索引、更新/查询数据等技术的实现方式。存储引擎是基于表的&#xff0c;而不是库的&#xff0c;所以存储引擎也可被称为表类型。 1&#xff09;在创…

golang闭包

【1】什么是闭包&#xff1a; 闭包就是一个函数和与其相关的引用环境组合的一个整体 【2】案例展示&#xff1a; package main import "fmt" //函数功能&#xff1a;求和 //函数的名字&#xff1a;getSum 参数为空 //getSum函数返回值为一个函数&#xff0c;这个函…