【发布时间】:2018-12-20 00:48:13
【问题描述】:
我想用 OpenWatcom 编译一个 Photoshop 滤镜插件。 该代码已经存在并且可以与 Visual Studio 完美配合。
函数如下所示:
extern "C" __declspec(export) void PluginMain(short selector, FilterRecordPtr pb, intptr_t *data, short *result);
它在 Visual C++ 中完美运行。请注意,没有明确指定调用约定(Adobe 没有在其 SDK 头文件中定义任何调用约定)。
虽然它在 VC++ 中有效,但在 OpenWatcom 中却不起作用,而且调用约定似乎不正确。 (即使使用“HelloWorld”函数,我也会遇到奇怪的行为,例如损坏的堆栈)。
在 Wikipedia,我查看了包含调用约定的表格:The table says,如果未指定调用约定,Watcom 会将参数放入寄存器“EAX、EDX、EBX、ECX”中,堆栈从右到左填充,并且被调用者清理堆栈。但是该表没有说明如果没有指定调用约定,Microsoft 编译器会做什么。
我确实认为 Visual Studio 默认使用不同的调用约定。
所以我尝试在 OpenWatcom 中指定 __stdcall、__cdecl 或 __pascal,但并没有太大帮助。
我的一个问题是,如果未指定任何内容,Visual Studio 的默认调用约定到底是什么?究竟将什么放入寄存器,在堆栈上的哪个方向,以及谁清理堆栈?我在任何地方都找不到此信息。
如果我知道确切的行为,我也许可以使用 OpenWatcom 中的“#pragma aux”功能来强制执行自定义调用约定?
或者您知道我可以尝试修复 OpenWatcom 中的调用约定的其他方法吗?
【问题讨论】:
-
VC++ 中的默认调用约定是 cdecl,尽管它可以通过命令行开关进行更改。 Watcom 调用约定似乎与 VC++ 的 fastcall 有点相似。出于好奇,您为什么要冒险使用一个采用自己的调用约定来构建插件的时下深奥的编译器,所以正确的 ABI 至关重要?
-
非常感谢您对 cdecl 的提示。我不知道,我认为 C++ 默认有 stdcall。 (你能把它作为答案发布吗?)我发现调用约定可以在 OpenWatcom 中的 Options -> C Compiler Switches -> Memory Model and Processor Switches 中更改。在那里,选择“Pentium Pro 基于堆栈的调用”(默认为“Pentium Pro 基于寄存器的调用”)。然后,一切正常:-)
-
对你的问题:有两个原因。第一个原因是,在我的休闲时间里,我喜欢用 1990 年代的旧软件工作和试验——毕竟,这些旧东西为我们的现代计算机技术铺平了道路。第二个原因是,我从事一个开源项目,在构建说明中我想告诉人们哪些编译器根本不工作,哪些正在工作以及如何配置它们。
-
很高兴它有帮助,我会将其移至 aswer。我完全理解对“老式”软件的迷恋,我怀疑这背后有某种动机。 :-)
标签: c++ visual-c++ calling-convention watcom