1

我正在通过以下方式访问 DLL:

int (__stdcall *Send) (char *);
Send = (int (__stdcall *)(char *)) GetProcAddress(hmModule,"Send");

原始调用使用:

int (FAR PASCAL *Send) (char FAR *);
Send = (int (FAR PASCAL *)(char FAR *))GetProcAddress(hmModule,"Send");

用 __stdcall 替换 FAR 和用 __stdcall 替换 PASCAL 有什么缺点吗

4

1 回答 1

3

删除 FAR 可能会将所有模块限制在同一段内。如果这是一个小程序,这可能很好。
编辑:然而,FAR 是过去的遗物,不适用于 win32 目标,并且在大多数情况下可以安全删除。

更改调用约定,只会影响与调用这些方法的外部模块的可能互操作。(它也可能对性能的影响很小,尽管我什至不确定)。

编辑:但是哇...!不!无法完成,我没有注意到这是针对 WinAPI 方法的,即当调用约定很容易为您定义时的一种方法……FAR 可能也是如此,它可能是需要的。

第二天编辑,用hya,OP的附加细节
目标函数在windef.h中定义为

extern "C" int APIENTRY Send (LPCSTR sCmd)

凭借对许多操作系统、编译器版本和本地定义值的支持,windef.h [相当不错] 是一个组合逻辑练习。对于大多数[非 MAC] 路径,并假设 windef.h 在该区域相对不变,APIENTRY归结为

...
#define APIENTRY  WINAPI
...
#define WINAPI   __stdcall

并且由于对于相同的路径,PASCAL 还产生__stdcall了第一个“谜”,在这个特定的上下文中(即通常非 MAC、MSC 编译器 8.0 或更高版本(或定义的编译器_STDCALL_SUPPORTED......)

关于 FAR 或什么都没有,(对我来说)不太清楚,但是,windef.h 宏中的大多数路径导致这两个宏什么都不产生。我认为这是因为编译器会使用目标内存模型来确定什么是短指针和长指针。无论如何,目标原型使用 LPCSTR,即“远/长”指针,这可能是编译器产生的。类似地,对于函数本身使用的 FAR 修饰符,这太不必要了,编译器会根据内存模型和/或隐式地为远调用存根。

所以,上面解释了为什么,是的,从to和 from to nothing所做的更改是可以的,并且应该产生一个功能二进制文件。(如果您更改编译器和/或目标操作系统,可能会重新检查等)。PASCAL__stdcallFAR

感谢您提出这个问题,因为这促使我重新审视我有一段时间没见过的问题。

于 2009-10-29T18:26:56.463 回答