使用GetProcAddress获取C++重载函数

2023-11-11

  GetProcAddress函数是用来在动态加载完动态链接库后,从链接库中获取函数地址的。它的用法如下:

FARPROC GetProcAddress(HMODULE hModule,LPCSTR lpProcName);

hModule参数就是LoadLibrary函数返回的动态链接库的句柄,lpProcName指向要获取的函数名称,函数名称以0结尾,对于函数名称是数值编号的lpProcName可以指定为编号数值。函数执行成功则返回要获取的函数的入口地址,失败则返回NULL。
  C++是支持函数重载的,也就是说允许多个不同的函数可以有同样的函数名。那么能不能通过函数名来获取C++的重载函数呢?从理论上来分析,由于GetProcAddress函数是通过函数名来唯一确定被调用函数的地址的,所以重载函数的地址是不可能用GetProcAddress通过函数名来获取的。
  MSDN对GetProcAddress函数进行解释时,说

The spelling and case of the function name pointed to by lpProcName must be identical to that in the EXPORTS statement of the source DLL’s module-definition (.DEF) file. The exported names of Win32 API functions may differ from the names you use when calling these functions in your code.

  翻译过来就是,lpProcName指向的函数名,它的拼写和大小写必须和DLL源代码中的模块定义源文件(.DEF)里的EXPORTS声明中指定的相同。Win32 API函数的导出名可能不同于你在代码中调用的这些函数名。
  那么如何处理函数的导出名与调用名不同呢?这个不同被宏隐含在相关的SDK头文件中。从MSDN对GetProcAddress函数解释可以看出,GetProcAddress函数实际是通过函数的导出名来在DLL中搜索需要的函数的。这样其实也解释了为何不能通过函数名来获取C++的重载函数了。C++的编译器为了保证导出函数名的唯一性,就无法将重载函数指定成相同的名称,于是就对函数名进行了处理,这样导出的函数名与源文件中定义的函数名不一样了,也就无法用源文件中的函数名来获取函数地址。这不仅仅是对于重载的C++函数,对于没有重载的C++函数也是一样的。
  通过上面的解释我们既知道GetProcAddress无法通过源文件中的函数名来获取C++的函数的原因,同时也为我们提供了通过GetProcAddress函数获取我们需要的C++函数的方法。我们通常的做法就是对要导出的C++函数加上extern “C”关键字,让该函数用标准C语言的方式来编译和导出的,但这样就无法定义重载函数,因为C语言不支持函数重载。
  不使用extern “C”关键字来声明C++函数的话,虽然能支持函数重载,但我们就只能使用函数的导出名来获取函数地址。我们有两种方式来获取函数的导出名,一种是按照C++编译器的函数名修饰规则来推导导出的函数名,具体的规则参见函数调用约定与名字修饰约定,不过如果函数导出名被重新定义为了其他名字,这个方式就不适用了。第二种方法是用工具来查看DLL中的导出表,像VS2013里就可以在使用命令行的命令dumpbin来察看导出表,具体使用方法如下:

dumpbin /exports dllname.dll

通过这个命令可以得到DLL中的函数的导出名和序数值,这样既可以使用序数值,也可以使用函数的导出名来获取函数地址了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用GetProcAddress获取C++重载函数 的相关文章

  • 为 DocumentDb 设置自定义 json 转换器

    我正在使用类型化 DocumentQuery 从 Azure DocumentDb 集合中读取文档 from f in client CreateDocumentQuery
  • EF Core 返回 null 关系,直到直接访问

    我有一些如下所示的模型 public class Mutant public long Id get set Relations public long OriginalCodeId get set public virtual Origi
  • 与 MinGW 的静态和动态/共享链接

    我想从一个简单的链接用法开始来解释我的问题 假设有一个图书馆z它可以编译为共享库 libz dll D libs z shared libz dll 或静态库 libz a D libs z static libz a 让我想要链接它 然后
  • 从结构调用 C++ 成员函数指针

    我找到了有关调用 C 成员函数指针和调用结构中的指针的信息 但我需要调用结构内部存在的成员函数指针 但我无法获得正确的语法 我在类 MyClass 的方法中有以下代码片段 void MyClass run struct int MyClas
  • 我担心我添加了太多接口

    我正在构建我的领域模型并继续重构它 正如我所做的那样 我发现我喜欢接口 因为它允许我根据接口为具体类型创建可重用的方法 控制器 视图 但是 我发现每次向域实体之一添加新属性时 我都会创建一个接口 例如 我有一个会员状态从抽象继承的对象Ent
  • C# 结构默认值

    我有一个方法 它接受一个包含许多具有基本数据类型的字段的结构 我想传递大部分默认值 但需要进行一些调整 但我了解结构声明中的基本字段不能包含默认值声明 例如struct S int a 42 现在是这样的 OptionsStruct opt
  • 维护 VS Test Project 中单元测试方法之间的上下文

    我想按顺序运行以下单元测试 使用随机数字的名称 密码等创建新客户 检索刚刚创建的客户并断言其属性包含相同的随机数 对同一用户调用 ForgotPassword 函数 并使用相同的随机数作为用户名 清楚地看到 我需要生成一次随机数 并在 3
  • 加载 QPixmap 数据的更好方法

    更好的方法来做到这一点 没有QImage QImage image width height QImage Format RGB888 memcpy image bits m frameRGB gt data 0 height width
  • DateTime.ParseExact - 为什么 yy 变成 2015 而不是 1915

    为什么 NET 假定以下年份是 2015 年 而不是 1915 年 var d DateTime ParseExact 20 11 15 dd MM yy new CultureInfo en GB 我想 它会尝试接近 但其背后是否有合理的
  • 当我尝试传递临时地址作为参数时,它是一个 UB 吗?

    对于以下 C 代码 include
  • 将 AutomationID 与 ListView 结合使用

    我正在尝试将 AutomationId 附加到列表视图中的项目 理想情况下 将项目名称绑定到显示的项目
  • C++网络序列化[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在寻找一种将 C 数据包序列化为网络流的解决方案 我在这里看到很多帖子提到人们 ACE 谷歌协议缓
  • Clang 5.0 上的 vsprintf 和 vsnprintf [-Wformat-nonliteral] 警告

    我有这段代码 static void err doit int errnoflag int level const char fmt va list ap int errno save unsigned long n char buf MA
  • 使用未命名命名空间而不是静态命名空间

    我可以假设在未命名命名空间中声明的对象相当于static namespace int x 1 static int x 2 FWIK 在这两种情况下 x将具有静态存储期限和内部链接 声明为的对象的所有规则也是如此static适用于未命名名称
  • 为什么我可以在另一个函数中定义一个函数?

    请参阅下面的代码 我在另一个函数中定义了一个函数 void test1 void void test2 void printf test2 n printf test1 n int main void test1 return 0 这个用法
  • c++ - <未解析的重载函数类型>

    在我的班级里叫Mat 我想要一个将另一个函数作为参数的函数 现在我有下面 4 个函数 但是在调用 print 时出现错误 第二行给了我一个错误 但我不明白为什么 因为第一行有效 唯一的区别是功能f不是班级成员Mat but f2是 失败的是
  • 如何防止 Lotus Notes 用户转发或复制通过 System.Net.Mail 发送的邮件?

    我想使用 SMTP 客户端 uiing microsft net 以 C 作为编程语言发送电子邮件 但是对于通过SMTP客户端发送的电子邮件 我们是否可以添加 禁止转发 或 禁止复制 等安全功能 我不希望电子邮件的收件人转发或复制电子邮件的
  • 尝试后终于没有被调用

    由于某种原因 在我的控制台应用程序中 我无法运行我的finally 块 我编写这段代码是为了测试finally块是如何工作的 所以它非常简单 static void Main int i 0 try int j 1 i Generate a
  • java有类似C#的属性吗? [复制]

    这个问题在这里已经有答案了 C 属性 我的意思是 get 和 set 方法 是一个非常有用的功能 java 也有类似 C 的属性吗 我的意思是我们如何在 java 中实现类似以下 C 代码的内容 public string Name get
  • NHibernate:无状态会话错误消息无法获取代理

    我正在使用 nHibernate 无状态会话来获取对象 更新一个属性并将对象保存回数据库 我不断收到错误消息 无状态会话无法获取代理 我在其他地方有类似的代码 所以我不明白为什么这不起作用 有谁知道问题可能是什么 我正在尝试更新Screen

随机推荐

  • Linux操作系统之线程创建

    文章目录 一 了解线程 二 线程的创建 一 了解线程 什么是线程 线程是进程内部的一条执行路径或执行序列 二 线程的创建 pthread creat 创建线程 pthread exit 只退出当前线程 pthread join 等待线程结束
  • matlab绘制奈奎图,matlab画奈奎斯特图

    基于matlab 的时域奈奎斯特定理验证课题名称 利用 matlab 检验采样定理 学院 计通学院 专业班级 通信 1402 2016 年 6 月 设计目的 1 掌握 matlab 的一些应用 奈奎斯特图和波特图解释 物理 自然科学 专业资
  • java-springboot、mybatis、redis相关面试题

    SpringBoot部分 相比Spring Spring Boot有哪些优点 Springboot是一个基于spring的框架 对spring做了大量简化 使开发流程更快 更高效 它大量简化maven依赖 管理了大量的基础依赖 基于注解配置
  • ovirt-engine平台vm rest-api新增接口字段

    背景 基于ovirt engine二次开发 为实现软删除功能 对现有的vm接口进行扩展字段 增加判断软删除字段以及软删除的时间字段 1 首先要再ovirt engine api model工程中 找到对应的资源类型 添加你需要的字段 typ
  • Similarity-Preserving Knowledge Distillation(2019ICCV)----论文阅读笔记

    Similarity Preserving Knowledge Distillation Abstract 1 Introduction 贡献 2 Method 3 Experiments 3 1 CIFAR 10 3 2 Transfer
  • 生成6位随机数

    随机生成六位不重复的数字 private static int generate6BitInt int arr 0 1 2 3 4 5 6 7 8 9 将数组随机打乱 据算法原理可知 重复概率 1 10 1 9 1 8 1 7 1 6 1
  • Yolov3 和 Yolov3-tiny目标检测算法理论与实现(TensorFlow2)

    文章目录 前言 一 Yolov3 和 Yolov3 tiny 1 网络结构 yolov3 tiny yolov3 框的回归 二 配置训练参数 1 目标检测数据集 2 设置anchor box 和classes 三 配置训练过程 四 模型预测
  • MySQL综合练习(50道)

    目录 一 准备工作 建表 插入数据 二 SQL练习 50道 1 查询 01 课程比 02 课程成绩高的学生的信息及课程分数 2 查询 01 课程比 02 课程成绩低的学生的信息及课程分数 3 查询平均成绩大于等于60分的同学的学生编号和学生
  • Git 检出、查看分支、切换分支、新建分支等简单命令

    Git 检出 查看分支 切换分支 新建分支等简单命令 首先需要安装 Git 并且配置 Git 环境变量 在需要检出工程的目录鼠标右键打开命令窗口 首先拿到 Git 仓库 SSH 地址或者 https 地址 1 执行 clone 命令 下面使
  • Ubuntu下文件权限管理

    参考 Ubuntu Linux 下文件权限管理 作者 莘莘 发布时间 2021 07 12 17 09 48 网址 https blog csdn net lcx1837 article details 118676383 spm 1001
  • GetLastError()返回值列表

    GetLastError 返回值列表 0 操作成功完成 1 功能错误 2 系统找不到指定的文件 3 系统找不到指定的路径 4 系统无法打开文件 5 拒绝访问 6 句柄无效 7 存储控制块被损坏 8 存储空间不足 无法处理此命令 9 存储控制
  • Debian小技巧1--常用软件服务配置方法

    Debian小技巧1 常用软件服务配置方法 最近 由于需要开始使用debian系统了 在使用过程会碰见一些经典的配置和操作方法 因此和往常一样记录下自己操作过程 后续将持续更新 优化 一方面以便于自己查阅 另一方面分享给有需要的人学习 1
  • 西门子触摸屏vb脚本从入门到精通_如何使用西门子触摸屏做一个弹窗?

    上篇文章我们讲到 西门子触摸屏变量的三种更新方式 根据命令 循环连续 循环使用 默认 这篇我们将一个实际案例 现场有台设备想在执行开机过程时触摸自动跳到执行过程的画面 假如PLC有个执行开机的变量M0 0 当M0 0为1的时候 自动切换画面
  • vue 评论小案例

  • vqvae详细解释

    模型综述 VQ VAE Vector Quantised Variational AutoEncoder 首先出现在论 Neural Discrete Representation Learning VAE假设隐向量分布服从高斯分布 VQV
  • 一些开源的,好看的前端组件/样式库

    以下是一些受欢迎的开源 CSS 样式库 Bootstrap https getbootstrap com Materialize CSS https materializecss com Bulma https bulma io Found
  • linux下测试磁盘的读写IO速度

    使用dd命令 这不是一个专业的测试工具 不过如果对于测试结果的要求不是很苛刻的话 平时可以使用来对磁盘的读写速度作一个简单的评估 另外由于这是一个免费软件 基本上 NIX系统上都有安装 首先了解两个特殊设备 dev null 伪设备 回收站
  • 使用OpenCV-python对植物图片进行分类

    文章目录 图片分类的思路和需要加载的库函数说明 核心代码分析 数据预处理 文件处理和命名匹配 数据预处理 特征提取和标签提取 学习模型 数据划分和模型训练 预测输出 利用训练好的模型进行图片分类 完整代码附录和运行结果 图片分类的思路和需要
  • vmware无法打开内核设备 打开模块DevicePowerOn电源失败

    无法打开内核设备 VMCIDev VMX 重叠 I O 操作在进 行中 你想要在安装 VMware Workstation 前重启吗 打开模块DevicePowerOn电源失败 启动VM时报错如上 解决方法一 亲测可行 对虚拟机相对应的 v
  • 使用GetProcAddress获取C++重载函数

    GetProcAddress函数是用来在动态加载完动态链接库后 从链接库中获取函数地址的 它的用法如下 FARPROC GetProcAddress HMODULE hModule LPCSTR lpProcName hModule参数就是