2501,编写dll
DLL
的优点
简单的说,dll
有以下几个优点
:
1
)节省内存
.同一个软件模块
,若是源码重用
,则会在不同可执行程序
中编译
,同时运行这些exe
时,会在内存
中重复加载
这些模块的二进制码
.
如果使用dll
,则只在内存
中加载一次
,所有使用该dll
的进程会共享此块内存
(当然,每个进程
会复制
一份的dll
中的全局变量
).
2
)不需编译
的软件系统升级
,若一个软件系统
使用了dll
,则改变该dll
(函数名
不变)时,系统升级
只需要切换此dll
即可,不需要重新编译整个系统
.
3
)多种语言可使用Dll
库,如用c编写的dll
可在vb
中调用.DLL
还做得很不够,因此在dll
的基础上发明了COM
技术,更好的解决
了一系列问题
.
最简单的dll
最简单的dll
并不比c的helloworld
难,只要一个DllMain
函数即可,包含objbase.h
头文件(支持COM
技术的一个头文件
).
若该头文件
名字难记,则用windows.h
也可以.源码如下:dll_nolib.cpp
#include <objbase.h>
#include <iostream.h>
BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, void* lpReserved)
{HANDLE g_hModule;switch(dwReason){case DLL_PROCESS_ATTACH:cout<<"Dll is attached!"<<endl;g_hModule = (HINSTANCE)hModule;break;case DLL_PROCESS_DETACH:cout<<"Dll is detached!"<<endl;g_hModule=NULL;break;}return true;
}
其中DllMain
是每个dll
的入口函数,如同c的主
函数一样.DllMain
带三个参数,hModule
表示本dll
的实例句柄
,dwReason
表示dll
当前所处的状态,如DLL_PROCESS_ATTACH
表示dll
刚刚被加载
到一个进程
中,DLL_PROCESS_DETACH
表示刚刚从一个进程
中卸载dll
.
当然还有表示加载到线程
中和从线程中卸载
的状态,这里省略.最后参数
是一个保存参数
.
如上,在一个进程
中加载dll
时,dll
打印"Dllisattached!"
语句;当从进程
中卸载dll
时,打印"Dllisdetached!"
语句.
编译dll
需要以下两条命令
:
cl /c dll_nolib.cpp
这条命令
会按obj
文件编译cpp
,若不使用/c参数
,则cl
还会继续链接obj
为exe
,但是这里是一个dll
,没有主
函数,因此会报错
.不要紧,继续使用链接命令
.
Link /dll dll_nolib.obj
这条命令
会生成dll_nolib.dll
.
加载DLL
(显式调用)
一般有两个方式
使用dll
,显式调用和隐式调用
.这里首先介绍显式调用
.编写一个客户程序
:dll_nolib_client.cpp
#include <windows.h>
#include <iostream.h>
int main(void)
{//加载的`dll`HINSTANCE hinst=::LoadLibrary("dll_nolib.dll");if (NULL != hinst){cout<<"dll loaded!"<<endl;}return 0;
}
注意,调用dll
使用LoadLibrary
函数,它的参数
就是dll
的路径和名字
,返回值
是dll
的句柄
.使用如下命令
编译链接客户:
Cl dll_nolib_client.cpp
并执行dll_nolib_client.exe
,得到如下结果:
Dllisattached!
dllloaded!
Dllisdetached!
以上结果表明客户已加载dll
.但是这样仅可在内存加载dll
,不能找到dll
中的函数
.
使用dumpbin
命令查看DLL
中的函数
Dumpbin
命令可查看一个dll
中的输出函数符号名
,输入如下命令
:
Dumpbin -exports dll_nolib.dll
查看
发现dll_nolib.dll
并没有输出函数
.
如何在dll
中定义输出函数
总体来说
有两个方法
,一个
是添加
一个def
定义文件,在此文件
中定义dll
中要输出的函数
;第二个
是在源码
中,待输出的函数
前加上__declspec(dllexport)
关键字.
Def
文件
首先写一个带输出函数
的dll
,源码如下:dll_def.cpp
#include <objbase.h>
#include <iostream.h>
void FuncInDll (void)
{cout<<"FuncInDll is called!"<<endl;
}
BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, void* lpReserved)
{HANDLE g_hModule;switch(dwReason){case DLL_PROCESS_ATTACH:g_hModule = (HINSTANCE)hModule;break;case DLL_PROCESS_DETACH:g_hModule=NULL;break;}return TRUE;
}
该dll
的def
文件如下:dll_def.def
;
//`dll_def`模块定义文件
;
LIBRARY dll_def.dll
DESCRIPTION '(c)2007-2009 Wang Xuebin'
EXPORTSFuncInDll @1 PRIVATE
def
的语法很简单
,首先是库
关键字,指定dll
的名字;然后一个可选
的描述
关键字.
最后是导出
关键字,后面写上dll
中所有要输出的函数名或变量名
,然后接上@及依次编号的数字
(从1到N
),最后接上修饰符
.
用如下命令
编译链接带def
文件的dll
:
Cl /c dll_def.cpp
Link /dll dll_def.obj /def:dll_def.def
再调用dumpbin
查看生成的dll_def.dll
:
Dumpbin -exports dll_def.dll
得到结果
.
观察这一行
.
1000001000FuncInDll
会发现该dll
输出了FuncInDll
函数.
显式调用DLL
中的函数
写一个dll_def.dll
的客户程序:dll_def_client.cpp
#include <windows.h>
#include <iostream.h>
int main(void)
{//定义一个函数指针typedef void (* DLLWITHLIB )(void);//定义一个函数指针变量DLLWITHLIB pfFuncInDll = NULL;//加载`dll`HINSTANCE hinst=::LoadLibrary("dll_def.dll");if (NULL != hinst){cout<<"dll loaded!"<<endl;}//找到`dll`的`FuncInDll`函数pfFuncInDll = (DLLWITHLIB)GetProcAddress(hinst, "FuncInDll");//调用`dll`里的函数if (NULL != pfFuncInDll){(*pfFuncInDll)();}return 0;
}
有两个地方
值得注意,第一是定义和使用函数指针
;第二是使用GetProcAddress
,来查找dll
中的函数地址
.
第一个参数
是DLL
的句柄
,即LoadLibrary
返回的句柄
,第二个参数
是dll
中的函数名
,即dumpbin
中输出的函数名
.
注意,这里的函数名
指的是编译后的函数名
,不一定等于dll
源码中的函数名
.
编译链接
该客户程序
,执行得到:
dllloaded!
FuncInDlliscalled!
即客户成功调用
了dll
中的FuncInDll
函数.
__declspec(dllexport)
为每个dll
写def
显得很麻烦,当前def
使用已比较少了,更多的是在源码
中,使用__declspec(dllexport)
定义dll
的输出函数
.
Dll
写法同上
,去掉def
文件,并在每个要输出的函数
前面加上__declspec(dllexport)
声明,如:
__declspec(dllexport) void FuncInDll (void)
这里提供一个dll
的dll_withlib.cpp
源程序,然后编译链接
.链接
时不需要指定/DEF
:参数,直接加/DLL
参数即可,
Cl /c dll_withlib.cpp
Link /dll dll_withlib.obj
然后使用dumpbin
命令查看,得到:
1 0 00001000 FuncInDll@@YAXXZ
可知编译
后的函数名
为FuncInDll@@YAXXZ
.
可用extern"C"
指令来命令c++
编译器按c编译器
的方式来命名该函数
.如下:
extern "C" __declspec(dllexport) void FuncInDll (void)
dumpbin
命令结果:
1000001000 FuncInDll
这样,显式调用
时只需查找函数名
为FuncInDll
的函数
即可成功.
隐式调用DLL
显式调用
显得非常复杂,每次都要LoadLibrary
,并且每个函数
都必须使用GetProcAddress
来得到函数指针
,对大量使用dll
函数的客户
是个困扰.
而隐式调用
可像使用c函数库
一样使用dll
中的函数,非常方便快捷
.
下面是一个隐式调用
的示例:dll
包含两个文件dll_withlibAndH.cpp
和dll_withlibAndH.h
.
代码如下:dll_withlibAndH.h
extern "C" __declspec(dllexport) void FuncInDll (void);
//dll_withlibAndH.cpp
#include <objbase.h>
#include <iostream.h>
#include "dll_withLibAndH.h"//看到没有,这就是增加的头文件
extern "C" __declspec(dllexport) void FuncInDll (void)
{cout<<"FuncInDll is called!"<<endl;
}
BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, void* lpReserved)
{HANDLE g_hModule;switch(dwReason){case DLL_PROCESS_ATTACH:g_hModule = (HINSTANCE)hModule;break;case DLL_PROCESS_DETACH:g_hModule=NULL;break;}return TRUE;
}
编译链接命令
:
Cl /c dll_withlibAndH.cpp
Link /dll dll_withlibAndH.obj
在隐式调用
时,需要在客户
中引入头文件
,并在链接
时指明dll
对应的lib
文件(dll
只要有函数输出
,则链接
时会产生一个与dll
同名的lib
文件)位置和名
.
然后如同调用api
函数库中的函数
一样调用dll
中的函数,不需要显式
的LoadLibrary
和GetProcAddress
.使用最方便
.
客户代码
如下:dll_withlibAndH_client.cpp
#include "dll_withLibAndH.h"
//注意路径,加载`dll`的或`项目`|设置|`链接`设置里
#pragma comment(lib,"dll_withLibAndH.lib")
int main(void)
{FuncInDll();//只要这样就可调用`dll`里的函数了return 0;
}
__declspec(dllexport)
和__declspec(dllimport
)配对使用
事实上不使用extern"C"
是可行
的,这时会按c++
的符号串编译函数
,如(FuncInDll@@YAXH@Z,FuncInDll@@YAXXZ
),当客户
也是c++
时,也能正确
的隐式调用
.
这时要考虑一种情况
:若DLL1.CPP
是源,DLL2.CPP
使用了DLL1
中的函数
,但同时DLL2
也是一个DLL
,也要输出
一些函数供Client.CPP
使用.
则在DLL2
中如何声明
所有的,既包含了从DLL1
中引入的函数
,还包括自己要输出的函数
的函数.此时就需要
同时使用__declspec(dllexport)
和__declspec(dllimport)
了.
前者用来装饰
本dll
中的输出函数
,后者用来装饰
从其它dll
中引入的函数
.
所有的源码
包括DLL1.H,DLL1.CPP,DLL2.H,DLL2.CPP,Client.cpp
.
值得关注的是DLL1
和DLL2
中都使用的一个编码方法
,见DLL2.H
#ifdef DLL_DLL2_EXPORTS
#define DLL_DLL2_API __declspec(dllexport)
#else
#define DLL_DLL2_API __declspec(dllimport)
#endif
DLL_DLL2_API void FuncInDll2(void);
DLL_DLL2_API void FuncInDll2(int);
在头文件
中这样定义DLL_DLL2_EXPORTS
和DLL_DLL2_API
宏,可确保DLL
端的函数用__declspec(dllexport)
装饰,而客户的函数
用__declspec(dllimport)
装饰.
当然,记得在编译dll
时加上参数/D "DLL_DLL2_EXPORTS"
,或干脆就在dll
的cpp
文件第一行
加上#define DLL_DLL2_EXPORTS
.
DLL
中的全局变量和对象
解决了重载函数
的问题,则dll
中的全局变量和对象
都不是问题了,只是有一点语法
注意.如源码所示:dll_object.h
#ifdef DLL_OBJECT_EXPORTS
#define DLL_OBJECT_API __declspec(dllexport)
#else
#define DLL_OBJECT_API __declspec(dllimport)
#endif
DLL_OBJECT_API void FuncInDll(void);
extern DLL_OBJECT_API int g_nDll;
class DLL_OBJECT_API CDll_Object {
public:CDll_Object(void);show(void);//`待办`:在此处添加你的方法.
};
Cpp
文件dll_object.cpp
如下:
#define DLL_OBJECT_EXPORTS
#include <objbase.h>
#include <iostream.h>
#include "dll_object.h"
DLL_OBJECT_API void FuncInDll(void)
{cout<<"FuncInDll is called!"<<endl;
}
DLL_OBJECT_API int g_nDll = 9;
CDll_Object::CDll_Object()
{cout<<"ctor of CDll_Object"<<endl;
}
CDll_Object::show()
{cout<<"function show in class CDll_Object"<<endl;
}
BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, void* lpReserved)
{HANDLE g_hModule;switch(dwReason){case DLL_PROCESS_ATTACH:g_hModule = (HINSTANCE)hModule;break;case DLL_PROCESS_DETACH:g_hModule=NULL;break;}return TRUE;
}
编译链接
完后Dumpbin
一下,可见输出了5个符号
:
1 0 00001040 0CDll_Object@@QAE@XZ2 1 00001000 4CDll_Object@@QAEAAV0@ABV0@@Z3 2 00001020 FuncInDll@@YAXXZ4 3 00008040 g_nDll@@3HA5 4 00001069 show@CDll_Object@@QAEHXZ
它们分别代表CDll_Object
类,类的构造器
,FuncInDll
函数,g_nDll
全局变量和类的显示
成员函数.下面是客户代码
:dll_object_client.cpp
#include "dll_object.h"
#include <iostream.h>
//注意路径,加载`dll`的或`项目`|设置|`链接`设置里
#pragma comment(lib,"dll_object.lib")
int main(void)
{cout<<"call dll"<<endl;cout<<"call function in dll"<<endl;FuncInDll();//只要这样就可调用`dll`里的函数了cout<<"global var in dll g_nDll ="<<g_nDll<<endl;cout<<"call member function of class CDll_Object in dll"<<endl;CDll_Object obj;obj.show();return 0;
}
运行该客户可见:
calldll
callfunctionindll
FuncInDlliscalled!
globalvarindllg_nDll=9
callmemberfunctionofclassCDll_Objectindll
ctorofCDll_Object
functionshowinclassCDll_Object
可知,客户
成功的访问了dll
中的全局变量
,并创建了dll
中定义的C++
对象,还调用
了该对象的成员函数
.
相关文章:
2501,编写dll
DLL的优点 简单的说,dll有以下几个优点: 1)节省内存.同一个软件模块,若是源码重用,则会在不同可执行程序中编译,同时运行这些exe时,会在内存中重复加载这些模块的二进制码. 如果使用dll,则只在内存中加载一次,所有使用该dll的进程会共享此块内存(当然,每个进程会复制一份的d…...
Linux命令汇总
1、帮忙类 --help 直接在当前窗口显示帮助 command --help man 创建新窗口显示帮助 man command 2、目录操作类 2.1、查看目录 ls:以列表方式,查看目录中内容 tree:以树状方式,查看目录中内容 2.2、创建、删除文件及目录 touch:创建…...
漏洞扫描工具之xray
下载地址:https://github.com/chaitin/xray/releases 1.9.11 使用文档:https://docs.xray.cool/tools/xray/Scanning 与burpsuite联动: https://xz.aliyun.com/news/7563 参考:https://blog.csdn.net/lza20001103/article/details…...
Java手写简单Merkle树
Java手写Merkle树代码 package com.blockchain.qgy.component;import com.blockchain.qgy.model.MerkleTreeNode; import com.blockchain.qgy.util.SHAUtil;import java.util.*;public class MerkleTree<T> {//merkle树private List<MerkleTreeNode<T>> lis…...
vue之pinia组件的使用
1、搭建pinia环境 cnpm i pinia #安装pinia的组件 cnpm i nanoid #唯一id,相当于uuid cnpm install axios #网络请求组件 2、存储读取数据 存储数据 >> Count.ts文件import {defineStore} from piniaexport const useCountStore defineStore(count,{// a…...
升级到Mac15.1后pod install报错
升级Mac后,Flutter项目里的ios项目运行 pod install报错, 遇到这种问题,不要着急去百度,大概看一下报错信息,每个人遇到的问题都不一样。 别人的解决方法并不一定适合你; 下面是报错信息: #…...
力扣【1049. 最后一块石头的重量 II】Java题解(背包问题)
让石头分成重量相同的两堆(尽可能相同),相撞之后剩下的石头就是最小的。进一步转化成容量为重量总喝一半的背包最多可以装多少质量的石头。这样就转化成了背包问题。 最后求结果时,我们所最多能装的时dp[target],那另一…...
CSS 图像、媒体和表单元素的样式化指南
CSS 图像、媒体和表单元素的样式化指南 1. 替换元素:图像和视频1.1 调整图像大小示例代码:调整图像大小 1.2 使用 object-fit 控制图像显示示例代码:使用 object-fit 2. 布局中的替换元素示例代码:Grid 布局中的图像 3. 表单元素的…...
寒武纪MLU370部署deepseek r1
文章目录 前言一、平台环境准备二、模型下载三、环境安装四、代码修改五、运行效果 前言 DeepSeek-R1拥有卓越的性能,在数学、代码和推理任务上可与OpenAI o1媲美。其采用的大规模强化学习技术,仅需少量标注数据即可显著提升模型性能,为大模…...
Spring的AOP的JoinPoint和ProceedingJoinPoint
Spring的AOP的JoinPoint 在Spring AOP中,JoinPoint 是一个核心接口,用于表示程序执行过程中的一个连接点(如方法调用或异常抛出)。它提供了访问当前被拦截方法的关键信息的能力。以下是关于 JoinPoint 的详细说明: 一…...
每日一道算法题
题目:单词接龙 II 给定两个单词(beginWord 和 endWord)和一个字典 wordList,找出所有从 beginWord 到 endWord 的最短转换序列。转换需遵循如下规则: 每次转换只能改变一个字母。转换过程中的中间单词必须是字典中的…...
Node.js——body-parser、防盗链、路由模块化、express-generator应用生成器
个人简介 👀个人主页: 前端杂货铺 🙋♂️学习方向: 主攻前端方向,正逐渐往全干发展 📃个人状态: 研发工程师,现效力于中国工业软件事业 🚀人生格言: 积跬步…...
Java小白入门教程:两大类型的修饰符以及示例
目录 一、访问控制修饰符 1、default 就是啥都不写的那种 2、private 私有 3、public 公开 4、protected 受保护的 二、非访问控制修饰符 1、static 静态 2、final 最终 3、abstract 抽象 4、synchronized 锁 5、transient 瞬态 6、volatile 易变 一、访问控制修饰符…...
正则表达式入门
入门 1、提取文章中所有的英文单词 //1.先创建一个Pattern对象,模式对象,可以理解成就是一个正则表达式对象 Pattern pattern Pattern.compile("[a-zA-Z]"); //2.创建一个匹配器对象 //理解:就是 matcher匹配器按照p…...
云原生(五十二) | DataGrip软件使用
文章目录 DataGrip软件使用 一、DataGrip基本使用 二、软件界面介绍 三、附件文件夹到项目中 四、DataGrip设置 五、SQL执行快捷键 DataGrip软件使用 一、DataGrip基本使用 1. 软件界面介绍 2. 附加文件夹到项目中【重要】 3. DataGrip配置 快捷键使用:C…...
如何成为一名 Python 全栈工程师攻略
## 从零基础到全栈工程师:Python 学习路线(细化版) **目标:** 掌握 Python 编程,并能独立开发全栈应用。 **学习路线:** ### 第一阶段:Python 基础 (4-6 周) **目标:** 掌握 Pyt…...
无需云端服务器: 三步实现DeepSeek大模型本地化部署deepseek、Ollama和Chatbox
🎉无需云端!三步实现DeepSeek大模型本地化部署😎 还在为云端AI服务的高昂费用而苦恼?是否总担心数据隐私会在云端泄露?别愁啦!DeepSeek R1——这款与OpenAI o1性能相媲美的开源大模型,结合Olla…...
mysql教程
MySQL 教程 一、简介 MySQL 是一个开源的关系型数据库管理系统,广泛应用于各种规模的项目中。以下是一些基础知识和常用操作。 二、安装与启动 安装:根据操作系统选择合适的安装包进行安装。启动:通过命令行或服务管理工具启动 MySQL 服务…...
【自学笔记】JavaWeb的重点知识点-持续更新
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 JavaWeb知识点一、基础概念二、项目结构三、Tomcat服务器四、数据库连接(JDBC)五、前端技术六、高级技术 总结 以下是JavaWeb知识点的MD格式…...
项目升级Sass版本或升级Element Plus版本遇到的问题
项目升级Sass版本或升级Element Plus版本遇到的问题 如果项目有需求需要用到高版本的Element Plus组件,则需要升级相对应的sass版本,Element 文档中有提示,2.8.5及以后得版本,sass最低支持的版本为1.79.0,所升级sass、…...
[EAI-028] Diffusion-VLA,能够进行多模态推理和机器人动作预测的VLA模型
Paper Card 论文标题:Diffusion-VLA: Scaling Robot Foundation Models via Unified Diffusion and Autoregression 论文作者:Junjie Wen, Minjie Zhu, Yichen Zhu, Zhibin Tang, Jinming Li, Zhongyi Zhou, Chengmeng Li, Xiaoyu Liu, Yaxin Peng, Chao…...
char和varchar的区别、varchar(?)中问号部分的含义、索引的作用
char和varchar的区别 char是固定长度类型,当输入字符不满设定的固定长度时依旧占用固定长度的空间,补充空字节。 最大长度为255个字符 优点:效率高,在涉及索引和排序时缺点:占用空间使用场景:存储密码的…...
.NET9增强OpenAPI规范,不再内置swagger
ASP.NETCore in .NET 9.0 OpenAPI官方文档ASP.NET Core API 应用中的 OpenAPI 支持概述 | Microsoft Learnhttps://learn.microsoft.com/zh-cn/aspnet/core/fundamentals/openapi/overview?viewaspnetcore-9.0https://learn.microsoft.com/zh-cn/aspnet/core/fundamentals/ope…...
qsort应用
每天都会收到ai个礼物,到第n天的时候,然然发现他的宿舍被礼物搞得一团糟,所以然然打算到超市买一个柜子装礼物。但是超市有m个柜子,每个柜子都有不同的容量bi,然然想知道每个柜子最多可以装多少天的礼物(可…...
仿真设计|基于51单片机的贪吃蛇游戏
目录 具体实现功能 设计介绍 51单片机简介 资料内容 仿真实现(protues8.7) 程序(Keil5) 全部内容 资料获取 具体实现功能 利用单片机8*8点阵实现贪吃蛇游戏的控制。 仿真演示视频: 51-基于51单片机的贪吃蛇游…...
Linux内核中的页面错误处理机制与按需分页技术
在现代操作系统中,内存管理是核心功能之一,而页面错误(Page Fault)处理机制是内存管理的重要组成部分。当程序访问一个尚未映射到物理内存的虚拟地址时,CPU会触发页面错误异常,内核需要捕获并处理这种异常,以决定如何响应,例如加载缺失的页面、处理权限错误等。Linux内…...
Baklib推动企业知识管理创新与效率提升的全面探讨
内容概要 在当今数字化转型的背景下,有效的知识管理显得尤为重要。知识是企业的核心资产,而传统的管理方式往往无法充分发挥这些知识的价值。因此,企业亟需一种高效、灵活的解决方案来应对这一挑战。Baklib作为一款先进的企业级知识管理平台…...
NLP自然语言处理通识
目录 ELMO 一、ELMo的核心设计理念 1. 静态词向量的局限性 2. 动态上下文嵌入的核心思想 3. 层次化特征提取 二、ELMo的模型结构与技术逻辑 1. 双向语言模型(BiLM) 2. 多层LSTM的层次化表示 三、ELMo的运行过程 1. 预训练阶段 2. 下游任务微调 四、ELMo的…...
计算机毕业设计Python+CNN卷积神经网络考研院校推荐系统 考研分数线预测 考研推荐系统 考研爬虫 考研大数据 Hadoop 大数据毕设 机器学习
温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 作者简介:Java领…...
【编译原理实验二】——自动机实验:NFA转DFA并最小化
本篇适用于ZZU的编译原理课程实验二——自动机实验:NFA转DFA并最小化,包含了实验代码和实验报告的内容,读者可根据需要参考完成自己的程序设计。 如果是ZZU的学弟学妹看到这篇,那么恭喜你,你来对地方啦! 如…...
Hive:复杂数据类型之Map函数
Map函数 是Hive里面的一种复杂数据类型, 用于存储键值对集合。Map中的键和值可以是基础类型或复合类型,这使得Map在处理需要关联存储信息的数据时非常有用。 定义map时,需声明2个属性: key 和 value , map中是 key value 组成一个元素 key-value, key必须为原始类…...
C++ 中的引用(Reference)
在 C 中,引用(Reference)是一种特殊的变量类型,它提供了一个已存在变量的别名。引用在很多场景下都非常有用,比如函数参数传递、返回值等。下面将详细介绍 C 引用的相关知识。 1. 引用的基本概念和语法 引用是已存在…...
密码学的数学基础1-整数 素数 和 RSA加密
数学公式推导是密码学的基础, 故开一个新的课题 – 密码学的数学基础系列 素数 / 质数 质数又称素数。 一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫做质数;否则称为合数(规定1既不是质数也不是合数࿰…...
Java锁自定义实现到aqs的理解
专栏系列文章地址:https://blog.csdn.net/qq_26437925/article/details/145290162 本文目标: 理解锁,能自定义实现锁通过自定义锁的实现复习Thread和Object的相关方法开始尝试理解Aqs, 这样后续基于Aqs的的各种实现将能更好的理解 目录 锁的…...
STM32-时钟树
STM32-时钟树 时钟 时钟...
android 圆形弹窗摄像头开发踩坑——源码————未来之窗跨平台操作
一、飘窗刷脸,拍照采用飘窗 刷脸认证安卓接口采用飘窗具有在不干扰用户主要操作的前提下以醒目方式引导用户完成认证,且能灵活定制样式以提升用户体验和认证效率的优点 二、踩坑只有一个扇形 <?xml version"1.0" encoding"utf-8&quo…...
markdown公式特殊字符
个人学习笔记 根号 在 Markdown 中,要表示根号 3,可以使用 LaTeX 语法来实现。常见的有以下两种方式: 行内公式形式:使用一对美元符号 $ 将内容包裹起来,即 $\sqrt{3}$ ,在支持 LaTeX 语法渲染的 Markdow…...
Web-3.0学习路线
方向学习内容✅ 区块链基础区块链、智能合约、共识机制✅ 智能合约Solidity / Rust(Ethereum / Solana)✅ 前端React.js, Next.js, Web3.js, ethers.js✅ 后端Node.js, Python, Golang(链上数据)✅ 存储IPFS, Arweave, Filecoin&a…...
【算法设计与分析】实验5:贪心算法—装载及背包问题
目录 一、实验目的 二、实验环境 三、实验内容 四、核心代码 五、记录与处理 六、思考与总结 七、完整报告和成果文件提取链接 一、实验目的 掌握贪心算法求解问题的思想;针对不同问题,会利用贪心算法进行问题建模、求解以及时间复杂度分析&#x…...
使用 cmake
使用前注意 : CMake是一种跨平台的构建系统,它用于管理软件构建过程,尤其适合多语言、多配置的项目。CMake不直接构建软件,而是生成特定构建工具(如Makefile或Visual Studio项目)所需的配置文件。 如果仅仅使用 qt 编…...
万物皆有联系:驼鸟和布什
布什?一块布十块钱吗?不是,大家都知道,美国有两个总统,叫老布什和小布什,因为两个布什总统(父子俩),大家就这么叫来着,目的是为了好区分。 布什总统的布什&a…...
PHP实现混合加密方式,提高加密的安全性(代码解密)
代码1: <?php // 需要加密的内容 $plaintext 授权服务器拒绝连接;// 1. AES加密部分 $aesKey openssl_random_pseudo_bytes(32); // 生成256位AES密钥 $iv openssl_random_pseudo_bytes(16); // 生成128位IV// AES加密(CBC模式)…...
分层多维度应急管理系统的设计
一、系统总体架构设计 1. 六层体系架构 #mermaid-svg-QOXtM1MnbrwUopPb {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-QOXtM1MnbrwUopPb .error-icon{fill:#552222;}#mermaid-svg-QOXtM1MnbrwUopPb .error-text{f…...
FFmpeg源码:av_base64_decode函数分析
一、引言 Base64(基底64)是一种基于64个可打印字符来表示二进制数据的表示方法。由于log2 646,所以每6个比特为一个单元,对应某个可打印字符。3个字节相当于24个比特,对应于4个Base64单元,即3个字节可由4个…...
算法随笔_30: 去除重复字母
上一篇:算法随笔_29:最大宽度坡_方法3-CSDN博客 题目描述如下: 给你一个字符串 s ,请你去除字符串中重复的字母,使得每个字母只出现一次。需保证 返回结果的字典序最小(要求不能打乱其他字符的相对位置)。 示例 1: …...
fpga系列 HDL:XILINX Vivado Vitis 高层次综合(HLS) 实现 EBAZ板LED控制(上)
目录 创建工程创建源文件并编写C代码C仿真综合仿真导出RTL CG导出RTL错误处理: 创建工程 创建源文件并编写C代码 创建源文件(Souces下的hlsv.h和hlsv.cpp,Test Bench下的test_hlsv1.cpp): hlsv1.h #ifndef HLSV1 #define HLSV1 #include &l…...
企业微信SCRM推动企业数字化转型实现高效客户管理与营销效益提升
内容概要 在当今数字化转型的大背景下,企业微信SCRM逐渐成为推动企业高效客户管理和提升营销效益的重要工具。说到SCRM,首先要了解它的定义。SCRM即社交化客户关系管理,通过整合社交媒体与客户管理,帮助企业更好地理解和服务客户…...
C++ 7
vector 底层原理和扩容过程 底层原理 ● vector 是 C 标准库中的一个容器,可以看作是一个动态数组,它的大小可以根据元素的增加而增长。它通过在堆上分配一段连续的内存空间存放元素,支持时间复杂度为 O(1 ) 的随机访问。 ● vec…...
论文阅读(七):贝叶斯因果表型网络解释遗传变异和生物学知识
1.论文链接:Bayesian Causal Phenotype Network Incorporating Genetic Variation and Biological Knowledge 摘要: 在分离群体中,数量性状基因座(QTL)定位可以确定对表型有因果效应的QTL。这些方法的一个共同特点是Q…...
数据库之PostgreSQL详解
一、PostgreSQL介绍 PostgreSQL是一个功能强大的 开源 的关系型数据库。底层基于C实现。 PostgreSQL的开源协议和Linux内核版本的开源协议是一样的。。BDS协议,这个协议基本和MIT开源协议一样,说人话,就是你可以对PostgreSQL进行一些封装&a…...