首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

关于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?》

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20201005A04IK600?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券