【问题标题】:Replacing FAR by nothing and PASCAL by __stdcall用 __stdcall 代替 FAR 和 PASCAL
【发布时间】:2009-10-29 18:21:36
【问题描述】:

我正在通过以下方式访问 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 有什么缺点吗

【问题讨论】:

    标签: c winapi dll call


    【解决方案1】:

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

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

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

    次日编辑,以及 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 修饰符,这也没有必要,因为编译器会根据内存模型和/或隐式地为远调用存根。

    所以,上面解释了为什么,是的,所做的更改PASCAL__stdcall 和从 FAR 到什么都没有都可以,应该会产生一个功能二进制。 (如果您更改编译器和/或目标操作系统,可能会重新检查等)。

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

    【讨论】:

    • 从 PASCAL 更改为 StdCall 不会对性能造成损害,就好像 DLL 被编译为允许 StdCall(大多数情况下都是这样),那么在访问上不会有任何差异。希望他理解 FAR 指的是位于与定义的指针起源不同的段中的地址。
    • @Reallyethical,对,感谢您确认没有性能差异,并且在 FAR 上一切正常。我对 OP 的确切需求等感到有点困惑。你说得对,大多数 API 都使用 __stdcall (又名 WINAPI),但我从这个问题中得到的暗示是这目前有效,所以切换调用 conv。肯定会破坏事情......也许我错过了一些'
    • 今天下午,当我得到 DLL 时,我寻找了一个工作示例,并在 C 中找到了一个带有旧的 FAR PASCAL 调用的示例。我怀疑代码是为以前版本的 DLL 编写的。我刚刚查看了源代码并使用了 APIENTRY (=>WINAPI =>__stdcall): extern "C" int APIENTRY Send (LPCSTR sCmd) 在 WinDef.h PASCAL 被定义为 __stdcall,所以它解释了为什么这两个工作( ?)。
    • @hya 查看我的编辑,加上您添加的详细信息,考虑到您的整体上下文(编译器/操作系统/内存模型...),这两个版本将生成完全相同的二进制文件关于对此 Windows 函数的调用,因此它们都可以工作。问候,
    • "删除FAR 可能会将所有模块限制在同一段内" ??当然,在 Win16 中,但实际上,现在是 2 世纪,问题被标记为 Win32。由于无论如何只有一个代码段,因此无论您是否使用FAR,您都受到限制。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-01-20
    • 1970-01-01
    • 2018-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多