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 func
    char *error = NULL;
    char* username = "jack";

    // load lib
    handle = dlopen("app.so", RTLD_LAZY); // lazy load
    if (!handle) {
        fprintf(stderr, "%s\n", dlerror()); // 错误信息输入到dlerror
        return 1;
    }
    
    // get func inner so
    func = dlsym(handle, "funcLauf");
    if ((error = dlerror()) != NULL)  { // 有错误输出
        fprintf(stderr, "%s\n", error);
        return 1;
    }
	
	// 函数调用
    printf("Result: %s\n", func(username));
    
    // close so ptr
    dlclose(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 调用动态库的差异

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

一键把家里孩子的涂鸦变为动画

最近&#xff0c;发现一款可以让涂鸦变成动画的工具&#xff08;Animated Drawings&#xff09;。 家里有孩子喜欢涂鸦的有福了&#xff0c;这是一个新的增加亲子互动的工具&#xff0c;可以让你孩子的涂鸦变成动画&#xff0c;动起来。 生成动画的过程非常简单&#xff0c;只…

Python解析Word文档的自动编号

关于自动编号的知识可以参考《在 Open XML WordprocessingML 中使用编号列表》 链接&#xff1a;https://learn.microsoft.com/zh-cn/previous-versions/office/ee922775(voffice.14) python-docx库并不能直接解析出Word文档的自动编号&#xff0c;因为原理较为复杂&#xff…

Macbook M芯片Maven的安装与配置

Macbook M芯片Maven的安装与配置 下载 搜索Maven 进入网站 https://maven.apache.org/download.cgi 点击Download 点击如下链接进行下载&#xff1b; 将下载好的文件放到你的指定位置 双击进行解压 配置环境变量 进入终端 在终端中输入 open ~/.bash_profile输入以下内…

CCNA 0基础入门

OSI & TCP/IP OSI参考模型 TCP/IP协议 应用层 ------↓表示层 ------>应用层会话层 ------↑传输层 ------>传输层网络层 ------>网络互联层链路层 ------>网络接口层物理层 ------>↑ 物理层 传输的信号以及网线以及接线 主要作用是产生并检测电…

16 DTLS协议

加密解密基本概念 什么是非对称加密 什么是公钥 这个就是谁都能获得的钥匙什么是私钥 只有一个人能获得 非对称加密就是公钥上的锁&#xff0c;私钥才能打开&#xff0c;私钥上的锁公钥才能打开。比如说就是地下党接头的时候&#xff0c;把一个信息放在盒子里&#xff0c;然…

pikachu靶场上的暴力破解

目录 一、暴力破解 基于表单的暴力破解 验证码绕过(on server) ​编辑 验证码绕过(on client) ​编辑 token防爆破? 二、暴力破解的相关知识点 (1)Burte Force&#xff08;暴力破解&#xff09;概述 (2)验证码的绕过原理 【验证码机制原理】 【客户端可能存在的安全…

智能型程控直流电子负载的介绍

智能型程控直流电子负载是一种高精度、高稳定性的电子设备&#xff0c;主要用于模拟各种实际负载情况&#xff0c;对电源设备进行测试和调试。它能够精确控制电流、电压、功率等参数&#xff0c;以满足不同应用场景的需求。 智能型程控直流电子负载的主要特点有以下几点&#x…

连接查询-外连接(FULL JOIN)、内连接(JOIN)、自身连接

一、表与表之间存在着某种联系&#xff0c;如果一个查询必须在多个表之间完成&#xff0c;则需要用到连接查询 二、连接查询的SQL查询语句 格式&#xff1a; SELECT A1&#xff0c;A2&#xff0c;...&#xff0c;Am FROM R1&#xff0c;R2&#xff0c;..&#xff0c;Rn WH…

推荐这3个APP,帮助你成长

扇贝阅读 当年考英语四级&#xff0c;扇贝阅读帮了很大的帮&#xff0c;这个应用我推荐给了好多同学使用&#xff0c;大家一致反馈不错。 提供很多原版的英文原著供学习&#xff0c;还自带翻译功能&#xff0c;并且提供单词本&#xff0c;遇到不懂的单词可以纪录到单词本中&am…

车载网络安全指南 网络安全框架(二)

返回总目录->返回总目录<- 目录 一、概述 二、网络安全组织管理 三、网络安全活动 四、支撑保障 一、概述 汽车电子系统网络安全活动框架包含汽车电子系统网络安全活动、组织管理以及支持保障。其中,网络安全管理活动是框架的核心,主要指汽车电子系统生命周期各阶段…

Day 14:2938. 区分黑球和白球

Leetcode 2938. 区分黑球和白球 桌子上有 n 个球&#xff0c;每个球的颜色不是黑色&#xff0c;就是白色。 给你一个长度为 n 、下标从 0 开始的二进制字符串 s&#xff0c;其中 1 和 0 分别代表黑色和白色的球。 在每一步中&#xff0c;你可以选择两个相邻的球并交换它们。 返…

E10:流程明细表表单字段值变化触发事件

效果– //window.WeFormSDK.showMessage("这是一个E10的提示", 3, 2);// 获取表单实例const weFormSdk window.WeFormSDK.getWeFormInstance();// 获取主表字段fieldIdconst bt weFormSdk.convertFieldNameToId("bt");const lcbh weFormSdk.convertFi…

第五讲:51单片机+RA8889驱动控制彩屏 完整源码说明 【 源码v1.2 】

51单片机驱动控制彩屏系列讲座 第一讲&#xff1a;单片机STC89C52RA8889驱动控制彩屏【 源码v1.0 】 第二讲&#xff1a;单片机STC89C52RA8889驱动控制彩屏 代码移植介绍 第三讲&#xff1a;单片机STC89C52RA8889驱动控制彩屏 代码的压缩&#xff08;Keil编译器&#xff09; 第…

C++ 中的负无穷大赋值

1&#xff0c;代码先行 示例&#xff1a; #include<iostream> #include<limits>using namespace std;int main() {float inf_pos numeric_limits<float>::infinity();float inf_neg -1*inf_pos;cout << "inf_pos " << inf_pos &l…

揭秘:消费1000,竟能领回2000?每天还有额外收入?

大家好&#xff0c;我是吴军&#xff0c;今天将为大家揭秘一种令人眼前一亮的商业模式——循环购模式。你可能会问&#xff0c;消费1000元&#xff0c;商家却送出了2000元的“好处”&#xff1f;每天还有钱领&#xff0c;这些钱还能提现&#xff1f;这究竟是怎么一回事&#xf…

[13] CUDA_Opencv联合编译过程

CUDA_Opencv联合编译过程 详细编译过程可见我之前的文章&#xff1a;Win10下OpencvCUDA联合编译详细教程&#xff08;版本455、460、470,亲测可用&#xff01;&#xff01;&#xff01;&#xff09;本文给出Windows\linux下的opencvcuda的编译总结&#xff0c;摘自 <基于GP…

CNS-BL30H系列直流无刷电机驱动器|电机参数配置方法

CNS-BL30H系列直流无刷电机驱动器|电机包含CNS-BL30HB、CNS-BL30HDN、CNS-BL30HSN&#xff0c;采用一驱二设计&#xff0c;可以同时驱动两个小于48V/1000W的直流无刷电机&#xff0c;体积小巧&#xff0c;安装方便&#xff0c;接线快捷&#xff0c;本文重点介绍CNS-BL30H系列直…

23种设计模式之组合模式

组合模式 1、定义 组合模式&#xff1a;组合多个对象形成树状结构以表示具有部分-整体关系的层次结构。组合模式让客户端可以统一对待单个对象和组合对象 2、组合模式结构 Component&#xff08;抽象构件&#xff09;&#xff1a;可以是接口或抽象类&#xff0c;为叶子构件…

时序分解 | Matlab实现SCSSA-VMD融合正余弦和柯西变异的麻雀搜索算法优化变分模态分解时间序列信号分解

时序分解 | Matlab实现SCSSA-VMD融合正余弦和柯西变异的麻雀搜索算法优化变分模态分解时间序列信号分解 目录 时序分解 | Matlab实现SCSSA-VMD融合正余弦和柯西变异的麻雀搜索算法优化变分模态分解时间序列信号分解效果一览基本介绍程序设计参考资料 效果一览 基本介绍 Matlab…

Spring—bean

一、bean的作用域 单例 默认化为&#xff1a;单例&#xff08;singleton&#xff09; SpringBean类&#xff1a; package com.hei.bean; public class SpringBean { public SpringBean(){System.out.println("Springbean的无参数构造方法执行了"); } } spring,xml…