数据线|关于GetProcAddress和名称修饰

名称修饰(decoration)的好处和坏处dllexport属性告诉链接器:请将指定的函数标记为导出并为它生成一个导出项 。
这个导出项是经过修饰的 , 对于导出多个重载的函数来说 , 导出修饰后的名称是十分必要的 。 但是 , 这也意味着:你传入到GetProcAddress函数中的函数字符串也需要是修饰版本的 。
从我们之前的几篇关于调用约定的文章中 , 我们知道 , 函数导出名称的修饰语法在各种硬件平台上是各不相同的 , 同时 , 随着调用约定的不同 , 导出的名称也会不同 。
举个例子 , 如果你从PowerPC平台上的一个DLL中导出一个函数 , 则你需要使用GetProcAddress(hinst “..SomeFunction”)来获取这个这个函数指针 。
如果是80386平台上使用extern “C” __stdcall调用约定 , 则需要使用GetProcAddress(hinst “_SomeFunction@8”) 。 如果使用的是__fastcall调用约定 , 则需要使用GetProcAddress(hinst “@SomeFunction@8”) 。
另外 , C++里的名称修饰和编译器厂商相关 。 如果是Microsoft C++编译器 , 则对于一个C++导出函数 , 需要使用GetProcAddress(hinst “?SomeFunction@@YGXHH@Z”) , 但是如果是Borland C++编译器 , 则需要另外的函数字符串来表示 。
所以 , 如果你开发了一个函数 , 你希望你的函数在各种不同的硬件平台 , 或者不同的语言 , 或者不同的C++编译器上都可以供客户调用 , 那么你必须导出它的未修饰版本 。
当生成一个DLL时 , 编译器会同时生成一个对应的LIB文件 , 这个LIB文件会将修饰后的名称翻译成未经修饰的版本 。 所以 , 举个例子 , 如果客户代码需要获取函数_GetTickCount@0 , 则这个LIB文件会将它翻译为kernel32!GetTickCount 。
课后练习题既然dllexport属性将导出函数绑定到某个特殊的硬件平台 , 编译器或者语言(通过将函数导出为修饰版本) , 那为什么MSVCRT.DLL会使用这个属性呢?
最后Raymond Chen的《The Old New Thing》是我非常喜欢的博客之一 , 里面有很多关于Windows的小知识 , 对于广大Windows平台开发者来说 , 确实十分有帮助 。
本文来自:《Why can’t I GetProcAddress a function I dllexport’ed?》
【数据线|关于GetProcAddress和名称修饰】
推荐阅读
- 辣椒|关于信仰、哲学与科学的迷思|東西堂主
- 高血脂|聚焦2021CROI大会,发布多项关于日常服药引发血脂问题的研究
- 新冠疫苗|这些关于新冠疫苗的健康知识,建议收藏!
- 糖尿病|糖吃多了就会得糖尿病?关于糖尿病的疑惑,这篇文章一次性解答!
- 低血糖|关于低血糖的那些事儿
- 疫苗接种|重磅!关于疫苗接种,天津最新消息来了!
- 疫苗接种|关于疫苗接种,最新通报
- 甲亢|王克珍:关于甲亢疾病你了解多少?
- 大豆|关于大豆运输安全,此文很实用
- 乙肝|关于乙肝的3个谣言,有人还深信不疑!快醒醒,别再信了
