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

如何优雅的导出函数

在开发过程中,经常会引用外部函数。方法主要有两种:

方法一:包含头文件并制定lib位置

  • 优点:使用简单
  • 缺点:lib和vs版本有关,不同的版本和编译模式可能导致编译失败

方法二:GetProcAddress

  • 优点:和编译器无关,只要获取函数地址即可使用
  • 缺点:需要一个个的函数去获取地址,相对麻烦

思考:有没有好的导出方式,可以直接包含头文件就使用呢?

  • 答案:有,参考Miniblink。在使用Miniblink的时候我们只需要包含头文件就可以直接引用导出函数。

源码分析:

  1. 作为dll的开发者,需要导出函数。模式如下:
#if defined(__cplusplus)
#define XYCENTER_EXTERN_C extern "C" 
#else
#define XYCENTER_EXTERN_C 
#endif#这里定义宏,根据函数参数个数不同,定义如下函数,一直延续到NXYCENTER_DEFINE_ITERATORN
#define XYCENTER_DECLARE_ITERATOR0(returnVal, name, description) \XYCENTER_EXTERN_C __declspec(dllexport) returnVal name();#define XYCENTER_DECLARE_ITERATOR1(returnVal, name, p1, description) \XYCENTER_EXTERN_C __declspec(dllexport) returnVal name(p1);#define XYCENTER_DECLARE_ITERATOR2(returnVal, name, p1, p2, description) \XYCENTER_EXTERN_C __declspec(dllexport) returnVal name(p1, p2);#格式按照【返回类型】【函数名】【参数】来维护导出函数列表0-N
#define XYCENTER_FOR_EACH_DEFINE_FUNCTION(ITERATOR0, ITERATOR1,ITERATOR2) \ITERATOR0(void, xyShutdown, "") \ITERATOR1(void, set_xycenterlog_handle,char *,"") \

#导出所有的函数0-N
XYCENTER_FOR_EACH_DEFINE_FUNCTION(XYCENTER_DECLARE_ITERATOR0, XYCENTER_DECLARE_ITERATOR1)

实现对应的导出函数即可:

void xyShutdown(){}
void set_xycenterlog_handle(char *){}
  1. 作为dll的符号使用者,分为两个步骤定义函数指针和对象,获取对应的符号地址
#定义不同参数个数的函数指针以及对应的对象0-N
#selectany 关键字,相关含义可以自行搜索
#define XYCENTER_DEFINE_ITERATOR0(returnVal, name, description) \typedef returnVal(XYCENTER_CALL_TYPE* xyFN_##name)(); \__declspec(selectany) xyFN_##name name = ((xyFN_##name)0);#define XYCENTER_DEFINE_ITERATOR1(returnVal, name, p1, description) \typedef returnVal(XYCENTER_CALL_TYPE* xyFN_##name)(p1); \__declspec(selectany) xyFN_##name name = ((xyFN_##name)0);#define XYCENTER_DEFINE_ITERATOR2(returnVal, name, p1,p2, description) \typedef returnVal(XYCENTER_CALL_TYPE* xyFN_##name)(p1,p2); \__declspec(selectany) xyFN_##name name = ((xyFN_##name)0);#获取函数地址
#define XYCENTER_GET_PTR_ITERATOR(name) \name = (xyFN_##name)GetProcAddress(hMod, #name); \if (!name) \MessageBoxA(((HWND)0), #name##" api not found", #name, 0);
#为了兼容上述维护的函数列表,所以需要多对应获取0-N的参数模式,这里直接使用变参模式
#define XYCENTER_GET_PTR_ITERATORN(returnVal, name,...) \XYCENTER_GET_PTR_ITERATOR(name);#最后一步设置dll路径并且初始化
#for each 不同参数的函数地址
XYCENTER_FOR_EACH_DEFINE_FUNCTION(XYCENTER_DEFINE_ITERATOR0, XYCENTER_DEFINE_ITERATOR1, XYCENTER_DEFINE_ITERATOR2)__declspec(selectany) const wchar_t* s_xyCenterDllPath = L"xyCenter.dll";inline void xyCenterSetWkeDllPath(const wchar_t* dllPath)
{s_xyCenterDllPath = dllPath;
}inline int xyCenterInitialize()
{HMODULE hMod = NULL;if (!hMod)hMod = LoadLibraryW(s_xyCenterDllPath);if (hMod) {XYCENTER_FOR_EACH_DEFINE_FUNCTION(XYCENTER_GET_PTR_ITERATORN, XYCENTER_GET_PTR_ITERATORN, XYCENTER_GET_PTR_ITERATORN);return 1;}return 0;
}

完整头文件,目前默认支持最多10个参数,用户可以自己扩展

使用宏XYCENTER_EXPORTS来决定是导入函数还是导出函数

#ifndef XYCENTER_DEFINE_H
#define XYCENTER_DEFINE_H#include <windows.h>//
#define XYCENTER_CALL_TYPE __cdecl#if defined(__cplusplus)
#define XYCENTER_EXTERN_C extern "C" 
#else
#define XYCENTER_EXTERN_C 
#endifnamespace xyCenter
{
#pragma pack(pop)/定义函数指针以及变量/
#define XYCENTER_DEFINE_ITERATOR0(returnVal, name, description) \typedef returnVal(XYCENTER_CALL_TYPE* xyFN_##name)(); \__declspec(selectany) xyFN_##name name = ((xyFN_##name)0);#define XYCENTER_DEFINE_ITERATOR1(returnVal, name, p1, description) \typedef returnVal(XYCENTER_CALL_TYPE* xyFN_##name)(p1); \__declspec(selectany) xyFN_##name name = ((xyFN_##name)0);#define XYCENTER_DEFINE_ITERATOR2(returnVal, name, p1,p2, description) \typedef returnVal(XYCENTER_CALL_TYPE* xyFN_##name)(p1,p2); \__declspec(selectany) xyFN_##name name = ((xyFN_##name)0);#define XYCENTER_DEFINE_ITERATOR3(returnVal, name, p1,p2,p3, description) \typedef returnVal(XYCENTER_CALL_TYPE* xyFN_##name)(p1,p2,p3); \__declspec(selectany) xyFN_##name name = ((xyFN_##name)0);#define XYCENTER_DEFINE_ITERATOR4(returnVal, name, p1,p2,p3,p4, description) \typedef returnVal(XYCENTER_CALL_TYPE* xyFN_##name)(p1,p2,p3,p4); \__declspec(selectany) xyFN_##name name = ((xyFN_##name)0);#define XYCENTER_DEFINE_ITERATOR5(returnVal, name, p1,p2,p3,p4,p5, description) \typedef returnVal(XYCENTER_CALL_TYPE* xyFN_##name)(p1,p2,p3,p4,p5); \__declspec(selectany) xyFN_##name name = ((xyFN_##name)0);#define XYCENTER_DEFINE_ITERATOR6(returnVal, name, p1,p2,p3,p4,p5,p6, description) \typedef returnVal(XYCENTER_CALL_TYPE* xyFN_##name)(p1,p2,p3,p4,p5,p6); \__declspec(selectany) xyFN_##name name = ((xyFN_##name)0);#define XYCENTER_DEFINE_ITERATOR7(returnVal, name, p1,p2,p3,p4,p5,p6,p7, description) \typedef returnVal(XYCENTER_CALL_TYPE* xyFN_##name)(p1,p2,p3,p4,p5,p6,p7); \__declspec(selectany) xyFN_##name name = ((xyFN_##name)0);#define XYCENTER_DEFINE_ITERATOR8(returnVal, name, p1,p2,p3,p4,p5,p6,p7,p8, description) \typedef returnVal(XYCENTER_CALL_TYPE* xyFN_##name)(p1,p2,p3,p4,p5,p6,p7,p8); \__declspec(selectany) xyFN_##name name = ((xyFN_##name)0);#define XYCENTER_DEFINE_ITERATOR9(returnVal, name, p1,p2,p3,p4,p5,p6,p7,p8,p9, description) \typedef returnVal(XYCENTER_CALL_TYPE* xyFN_##name)(p1,p2,p3,p4,p5,p6,p7,p8,p9); \__declspec(selectany) xyFN_##name name = ((xyFN_##name)0);#define XYCENTER_DEFINE_ITERATOR10(returnVal, name, p1,p2,p3,p4,p5,p6,p7,p8,p9,p10, description) \typedef returnVal(XYCENTER_CALL_TYPE* xyFN_##name)(p1,p2,p3,p4,p5,p6,p7,p8,p9,p10); \__declspec(selectany) xyFN_##name name = ((xyFN_##name)0);/获取dll函数指针地址/
#define XYCENTER_GET_PTR_ITERATOR(name) \name = (xyFN_##name)GetProcAddress(hMod, #name); \if (!name) \MessageBoxA(((HWND)0), #name##" api not found", #name, 0);#define XYCENTER_GET_PTR_ITERATORN(returnVal, name,...) \XYCENTER_GET_PTR_ITERATOR(name);/定义导出函数/
#define XYCENTER_DECLARE_ITERATOR0(returnVal, name, description) \XYCENTER_EXTERN_C __declspec(dllexport) returnVal name();#define XYCENTER_DECLARE_ITERATOR1(returnVal, name, p1, description) \XYCENTER_EXTERN_C __declspec(dllexport) returnVal name(p1);#define XYCENTER_DECLARE_ITERATOR2(returnVal, name, p1, p2, description) \XYCENTER_EXTERN_C __declspec(dllexport) returnVal name(p1, p2);#define XYCENTER_DECLARE_ITERATOR3(returnVal, name, p1, p2,p3, description) \XYCENTER_EXTERN_C __declspec(dllexport) returnVal name(p1, p2,p3);#define XYCENTER_DECLARE_ITERATOR4(returnVal, name, p1, p2,p3,p4, description) \XYCENTER_EXTERN_C __declspec(dllexport) returnVal name(p1, p2,p3,p4);#define XYCENTER_DECLARE_ITERATOR5(returnVal, name, p1, p2,p3,p4,p5, description) \XYCENTER_EXTERN_C __declspec(dllexport) returnVal name(p1, p2,p3,p4,p5);#define XYCENTER_DECLARE_ITERATOR6(returnVal, name, p1, p2,p3,p4,p5,p6, description) \XYCENTER_EXTERN_C __declspec(dllexport) returnVal name(p1, p2,p3,p4,p5,p6);#define XYCENTER_DECLARE_ITERATOR7(returnVal, name, p1, p2,p3,p4,p5,p6,p7, description) \XYCENTER_EXTERN_C __declspec(dllexport) returnVal name(p1, p2,p3,p4,p5,p6,p7);#define XYCENTER_DECLARE_ITERATOR8(returnVal, name, p1, p2,p3,p4,p5,p6,p7,p8, description) \XYCENTER_EXTERN_C __declspec(dllexport) returnVal name(p1, p2,p3,p4,p5,p6,p7,p8);#define XYCENTER_DECLARE_ITERATOR9(returnVal, name, p1, p2,p3,p4,p5,p6,p7,p8,p9, description) \XYCENTER_EXTERN_C __declspec(dllexport) returnVal name(p1, p2,p3,p4,p5,p6,p7,p8,p9);#define XYCENTER_DECLARE_ITERATOR10(returnVal, name, p1, p2,p3,p4,p5,p6,p7,p8,p9,p10, description) \XYCENTER_EXTERN_C __declspec(dllexport) returnVal name(p1, p2,p3,p4,p5,p6,p7,p8,p9,p10);// 以下是xyCenter的导出函数。格式按照【返回类型】【函数名】【参数】来排列
#define XYCENTER_FOR_EACH_DEFINE_FUNCTION(ITERATOR0, ITERATOR1,ITERATOR2,ITERATOR3,ITERATOR4,ITERATOR5,ITERATOR6,ITERATOR7,ITERATOR8,ITERATOR9,ITERATOR10) \ITERATOR0(int, get_msgno, "获取通知消息的消息code") \ITERATOR1(void, set_log_handle, PFN_XYCENTERLOG_HANDLE,"设置日志句柄") \ITERATOR1(bool, write_data, XyCenterData *,"写入用户共享数据") \ITERATOR1(bool, read_data, XyCenterData&,"获取用户数据") \
//导出函数
#ifdef XYCENTER_EXPORTSXYCENTER_FOR_EACH_DEFINE_FUNCTION(XYCENTER_DECLARE_ITERATOR0, XYCENTER_DECLARE_ITERATOR1, XYCENTER_DECLARE_ITERATOR2,\XYCENTER_DECLARE_ITERATOR3,XYCENTER_DECLARE_ITERATOR4, XYCENTER_DECLARE_ITERATOR5, XYCENTER_DECLARE_ITERATOR6,\XYCENTER_DECLARE_ITERATOR7, XYCENTER_DECLARE_ITERATOR8,XYCENTER_DECLARE_ITERATOR9, XYCENTER_DECLARE_ITERATOR10)//引入导出函数
#elseXYCENTER_FOR_EACH_DEFINE_FUNCTION(XYCENTER_DEFINE_ITERATOR0, XYCENTER_DEFINE_ITERATOR1, XYCENTER_DEFINE_ITERATOR2,\XYCENTER_DEFINE_ITERATOR3, XYCENTER_DEFINE_ITERATOR4, XYCENTER_DEFINE_ITERATOR5, XYCENTER_DEFINE_ITERATOR6,\XYCENTER_DEFINE_ITERATOR7, XYCENTER_DEFINE_ITERATOR8, XYCENTER_DEFINE_ITERATOR9, XYCENTER_DEFINE_ITERATOR10)__declspec(selectany) const wchar_t* s_xyCenterDllPath = L"xyCenter.dll";inline void SetWkeDllPath(const wchar_t* dllPath){s_xyCenterDllPath = dllPath;}inline bool Initialize(){HMODULE hMod = NULL;if (!hMod)hMod = LoadLibraryW(s_xyCenterDllPath);if (hMod) {XYCENTER_FOR_EACH_DEFINE_FUNCTION(XYCENTER_GET_PTR_ITERATORN, XYCENTER_GET_PTR_ITERATORN, XYCENTER_GET_PTR_ITERATORN,\XYCENTER_GET_PTR_ITERATORN, XYCENTER_GET_PTR_ITERATORN, XYCENTER_GET_PTR_ITERATORN, XYCENTER_GET_PTR_ITERATORN,\XYCENTER_GET_PTR_ITERATORN, XYCENTER_GET_PTR_ITERATORN, XYCENTER_GET_PTR_ITERATORN, XYCENTER_GET_PTR_ITERATORN);return true;}return false;}
#endif // DEBUG#endif // XYCENTER_DEFINE_H};

此时我们只需要包含头文件,并且初始化一下即可直接使用导出函数。

相关文章:

如何优雅的导出函数

在开发过程中&#xff0c;经常会引用外部函数。方法主要有两种&#xff1a; 方法一&#xff1a;包含头文件并制定lib位置 优点&#xff1a;使用简单缺点&#xff1a;lib和vs版本有关&#xff0c;不同的版本和编译模式可能导致编译失败 方法二&#xff1a;GetProcAddress 优…...

c++多重继承

1.概论多重继承是否有必要吗&#xff1f;这个问题显然是一个哲学问题&#xff0c;正确的解答方式是根据情况来看&#xff0c;有时候需要&#xff0c;有时候不需要&#xff0c;这显然是一句废话&#xff0c;有点像上马克思主义哲学或者中庸思。但是这个问题和那些思想一样&#…...

15_FreeRtos计数信号量优先级翻转互斥信号量

目录 计数型信号量 计数型信号量相关API函数 计数型信号量实验源码 优先级翻转简介 优先级翻转实验源码 互斥信号量 互斥信号量相关API函数 互斥信号量实验源码 计数型信号量 计数型信号量相当于队列长度大于1的队列&#xff0c;因此计数型信号量能够容纳多个资源,这在…...

二叉树(一)

二叉树&#xff08;一&#xff09;1.树的概念2.树的相关概念3.树的表示4.树在实际中的运用5.二叉树概念及结构6.特殊的二叉树7.二叉树的性质&#x1f31f;&#x1f31f;hello&#xff0c;各位读者大大们你们好呀&#x1f31f;&#x1f31f; &#x1f680;&#x1f680;系列专栏…...

【SCL】1200案例:天塔之光数码管显示液体混合水塔水位

使用scl编写天塔之光&数码管显示&液体混合&水塔水位 文章目录 目录 文章目录 前言 一、案例1&#xff1a;天塔之光 1.控制要求 2.编写程序 3.效果 二、案例2&#xff1a;液体混合 1.控制要求 2.编写程序 三、案例3&#xff1a;数码管显示 1.控制要求 2.编写程序 3…...

5.1配置IBGP和EBGP

5.2.1实验1&#xff1a;配置IBGP和EBGP 实验目的 熟悉IBGP和EBGP的应用场景掌握IBGP和EBGP的配置方法 实验拓扑 实验拓扑如图5-1所示&#xff1a; 图5-1&#xff1a;配置IBGP和EBGP 实验步骤 IP地址的配置 R1的配置 <Huawei>system-view Enter system view, return …...

c++中超级详细的一些知识,新手快来

目录 2.文章内容简介 3.理解虚函数表 3.1.多态与虚表 3.2.使用指针访问虚表 4.对象模型概述 4.1.简单对象模型 4.2.表格驱动模型 4.3.非继承下的C对象模型 5.继承下的C对象模型 5.1.单继承 5.2.多继承 5.2.1一般的多重继承&#xff08;非菱形继承&#xff09; 5.2…...

[答疑]经营困难时期谈建模和伪创新-长点心和长点良心

leonll 2022-11-26 9:53 我们今年真是太难了……&#xff08;此处删除若干字&#xff09;……去年底就想着邀请您来给我们讲课&#xff0c;现在也没有实行。我想再和我们老大提&#xff0c;您觉得怎么说个关键理由&#xff0c;这样的形势合适引进UML开发流程&#xff1f; UML…...

计算机基础知识

计算机网络的拓扑结构 一、OSI 7层网络模型是指什么&#xff1f; 7层分别是什么&#xff1f;每层的作用是什么&#xff1f; OSI7层模型是 国际标准化组织(ISO)制定的一个用于计算机或通信系统间互联的标准体系。 每层功能:&#xff08;自底向上&#xff09; 物理层:建立、…...

Java爬虫—WebMagic

一&#xff0c;WebMagic介绍WebMagic企业开发&#xff0c;比HttpClient和JSoup更方便一&#xff09;&#xff0c;WebMagic架构介绍WebMagic有DownLoad&#xff0c;PageProcessor&#xff0c;Schedule&#xff0c;Pipeline四大组件&#xff0c;并有Spider将他们组织起来&#xf…...

[软件工程导论(第六版)]第2章 可行性研究(复习笔记)

文章目录2.1 可行性研究的任务2.2 可行性研究过程2.3 系统流程图2.4 数据流图概念2.5 数据字典2.6 成本/效益分析2.1 可行性研究的任务 可行性研究的目的 用最小的代价在尽可能短的时间内确定问题是否能够解决。 可行性研究的3个方面 &#xff08;1&#xff09;技术可行性&…...

Mac下安装Tomcat以及IDEA中的配置

安装brew 打开终端输入以下命令&#xff1a; /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" 搜索tomcat版本&#xff0c;输入以下命令&#xff1a; brew search tomcat 安装自己想要的版本&#xff0c;例…...

【Linux详解】——文件基础(I/O、文件描述符、重定向、缓冲区)

&#x1f4d6; 前言&#xff1a;本期介绍文件基础I/O。 目录&#x1f552; 1. 文件回顾&#x1f558; 1.1 基本概念&#x1f558; 1.2 C语言文件操作&#x1f564; 1.2.1 概述&#x1f564; 1.2.2 实操&#x1f564; 1.2.3 OS接口open的使用&#xff08;比特位标记&#xff09;…...

HomMat2d

1.affine_trans_region&#xff08;区域的任意变换&#xff09; 2.hom_mat2d_identity&#xff08;创建二位变换矩阵&#xff09; 3.hom_mat2d_translate&#xff08;平移&#xff09; 4.hom_mat2d_scale&#xff08;缩放&#xff09; 5.hom_mat2d_rotate&#xff08;旋转 &…...

Python3 JSON 数据解析

Python3 JSON 数据解析 JSON (JavaScript Object Notation) 是一种轻量级的数据交换格式。 Python3 中可以使用 json 模块来对 JSON 数据进行编解码&#xff0c;它包含了两个函数&#xff1a; json.dumps(): 对数据进行编码。json.loads(): 对数据进行解码。 在 json 的编解码…...

Homebrew 安装遇到的问题

Homebrew 安装遇到的问题 例如&#xff1a;第一章 Python 机器学习入门之pandas的使用 文章目录Homebrew 安装遇到的问题前言一、安装二、遇到的问题1.提示 zsh: command not found: brew三、解决问题前言 使用 Homebrew 能够 安装 Apple&#xff08;或您的 Linux 系统&#…...

Metasploit框架基础(二)

文章目录前言一、Meatsplooit的架构二、目录结构datadocumentationlibmodulesplugins三、Measploit模块四、Metasploit的使用前言 Metasploit是用ruby语言开发的&#xff0c;所以你打开软件目录&#xff0c;会发现很多.rb结尾的文件。ruby是一门OOP的语言。 一、Meatsplooit的…...

c++容器

1、vector容器 1.1性质 a&#xff09;该容器的数据结构和数组相似&#xff0c;被称为单端数组。 b&#xff09;在存储数据时不是在原有空间上往后拓展&#xff0c;而是找到一个新的空间&#xff0c;将原数据深拷贝到新空间&#xff0c;释放原空间。该过程被称为动态拓展。 vec…...

Vue.js如何实现对一千张图片进行分页加载?

目录 vue处理一千张图片进行分页加载 分页加载、懒加载---概念介绍&#xff1a; 思路&#xff1a; 开发过程中&#xff0c;如果后端一次性返回你1000多条图片或数据&#xff0c;那我们前端应该怎么用什么思路去更好的渲染呢&#xff1f; 第一种&#xff1a;我们可以使用分页…...

计算机网络复习(六)

考点&#xff1a;MIME及其编码&#xff08;base64,quoted-printable)网络协议http是基于什么协议&#xff0c;应用层到网络层基于什么协议6-27.试将数据 11001100 10000001 00111000 进行 base64 编码&#xff0c;并得到最后传输的 ASCII 数据。答&#xff1a;先将 24 比特的二…...

浅谈 React Hooks

React Hooks 是 React 16.8 引入的一组 API&#xff0c;用于在函数组件中使用 state 和其他 React 特性&#xff08;例如生命周期方法、context 等&#xff09;。Hooks 通过简洁的函数接口&#xff0c;解决了状态与 UI 的高度解耦&#xff0c;通过函数式编程范式实现更灵活 Rea…...

【第二十一章 SDIO接口(SDIO)】

第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...

工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配

AI3D视觉的工业赋能者 迁移科技成立于2017年&#xff0c;作为行业领先的3D工业相机及视觉系统供应商&#xff0c;累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成&#xff0c;通过稳定、易用、高回报的AI3D视觉系统&#xff0c;为汽车、新能源、金属制造等行…...

Java面试专项一-准备篇

一、企业简历筛选规则 一般企业的简历筛选流程&#xff1a;首先由HR先筛选一部分简历后&#xff0c;在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如&#xff1a;Boss直聘&#xff08;招聘方平台&#xff09; 直接按照条件进行筛选 例如&#xff1a…...

大学生职业发展与就业创业指导教学评价

这里是引用 作为软工2203/2204班的学生&#xff0c;我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要&#xff0c;而您认真负责的教学态度&#xff0c;让课程的每一部分都充满了实用价值。 尤其让我…...

企业如何增强终端安全?

在数字化转型加速的今天&#xff0c;企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机&#xff0c;到工厂里的物联网设备、智能传感器&#xff0c;这些终端构成了企业与外部世界连接的 “神经末梢”。然而&#xff0c;随着远程办公的常态化和设备接入的爆炸式…...

在Ubuntu24上采用Wine打开SourceInsight

1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...

【笔记】WSL 中 Rust 安装与测试完整记录

#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统&#xff1a;Ubuntu 24.04 LTS (WSL2)架构&#xff1a;x86_64 (GNU/Linux)Rust 版本&#xff1a;rustc 1.87.0 (2025-05-09)Cargo 版本&#xff1a;cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...

C#中的CLR属性、依赖属性与附加属性

CLR属性的主要特征 封装性&#xff1a; 隐藏字段的实现细节 提供对字段的受控访问 访问控制&#xff1a; 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性&#xff1a; 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑&#xff1a; 可以…...

【JVM面试篇】高频八股汇总——类加载和类加载器

目录 1. 讲一下类加载过程&#xff1f; 2. Java创建对象的过程&#xff1f; 3. 对象的生命周期&#xff1f; 4. 类加载器有哪些&#xff1f; 5. 双亲委派模型的作用&#xff08;好处&#xff09;&#xff1f; 6. 讲一下类的加载和双亲委派原则&#xff1f; 7. 双亲委派模…...