通过调用约定诊断一个常见问题

通过调用约定诊断一个常见问题

作者:BlogUpdater |  时间:2021-05-16 |  浏览:1843 |  评论已关闭 条评论

事情是这样的
有一位开发者朋友问了有关”未能解析的外部引用”的问题。我的一个目标之一是:通过向你展示底层的工作原理,这样你就可以自己解决问题。这里的外部引用问题,是可以通过我之前博文里介绍的调用约定的文章来解决的。

首先,我们来看看具体的报错信息。
Undefined symbol: ‘__stdcall(0) pl_pvcam_init (_pl_pvcam_init@0)’ referenced from ‘_main’ in Acquisition.c:15

这里的”_pl_pvcam_init@0″,你可以看到里面的开头的下划线以及结尾的”@0″,这意味着:这个函数使用了标准的__stdcall调用约定。(我们通过链接器的未修饰名称来确认了这一点。)

所以,你的”_main”函数想要以__stdcall调用约定来使用pl_pvcam_init函数。但是链接器在你的库中没有找到它。

如果你再仔细的在链接的库中找找,则你会发现你想要的符号是以另外一种修饰存在于库中的。然后,你对这种修饰进行解码,我的第六感告诉我,当你解码的时候,你会发现:你想要链接的函数符号,采用了__cdecl调用约定,也即:”_pl_pvcam_init”。

至此,你应该可以看到问题所在了。你的调用代码使用了__stdcall调用约定,但是被调用函数却使用了__cdecl调用约定。因为两种调用约定不相匹配,导致了链接器报错。

解决方案
解决这个问题的方法是,我们可以在pl_pvcam_init函数声明所在的头文件中指定正确的调用约定。我的第六感再次告诉我:头文件头文件根本没有指定任何调用约定,这使该文件受到你的项目环境中的调用约定(似乎是__stdcall)的影响。 但是头文件的作者希望__cdecl是默认的调用约定。
所以,只需要在函数上施加正确的调用约定,一切就OK了。

最后
Raymond Chen的《The Old New Thing》是我非常喜欢的博客之一,里面有很多关于Windows的小知识,对于广大Windows平台开发者来说,确实十分有帮助。
本文来自:《Diagnosing a problem with calling conventions》

最近我写了个东西
正如你们所知道的,拓扑梅尔智慧办公平台(Topomel Box)是一款绿色软件,主要面向经常使用电脑的朋友。它提供了各种提升办公效率的小功能,同时操作上尽可能地简单方便。
我想:你值得拥有。

标签:

评论已关闭。