我正在通过以下方式访问 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");
用 nothing 代替 FAR 并用 __stdcall 代替 PASCAL 有什么缺点吗
最佳答案
删除 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 宏中的大多数路径也导致这两个宏不产生任何结果。我认为这是因为编译器会使用目标内存模型来确定什么是短指针和长指针。无论如何,目标原型(prototype)使用 LPCSTR,即“远/长”指针,这可能是编译器产生的。类似地,对于与函数本身一起使用的 FAR 修饰符,这也没有必要,因为编译器会根据内存模型和/或隐式地对远调用进行 stub 。
所以,上面解释了为什么,是的,所做的更改从 PASCAL
到 __stdcall
和从 FAR
什么都没有没问题,应该会产生一个功能性的二进制文件。 (如果您更改编译器和/或目标操作系统,可能需要重新检查等)。
感谢您提出这个问题,因为这促使我重新审视我有一段时间没见过的问题。
关于c - 用 __stdcall 替换 FAR 和 PASCAL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1645643/