我正在使用 Delphi 为 Excel 制作一个 XLL 插件,这涉及对 xlcall32.dll 的Excel4v函数进行大量调用。然而,我猜这里很少有 Delphi 专家使用过那个特定的 API,我希望这个问题也可能在其他 API 中被观察到。
在 C 语言中,特别是在Microsoft Excel 2007 XLL SDK附带的 xlcall.h 文件中,Excel4v 定义为:
int pascal Excel4v(int xlfn, LPXLOPER operRes, int count, LPXLOPER opers[]);
在德尔福我正在使用:
function Excel4v(xlfn: Integer; operRes: LPXLOPER; count: Integer;
opers: array of LPXLOPER): Integer; stdcall; external 'xlcall32.dll';
LPXLOPER 是指向结构(在 C 中)或记录(在 Delphi 中)的指针。
我一直在做关于在 Delphi 中声明 C 函数的功课(这篇优秀的文章很有帮助),我认为我正确地声明了 Excel4v。但是,从 Delphi 代码调用该函数会导致异常(“访问冲突......”是我一直看到的),除非它们后面跟着以下行:
asm pop sink; end;
其中“sink”在某处定义为整数。
我对组装一无所知......所以我没有办法尝试用“asm pop sink; end;”来修复异常。但是“asm pop sink; end;” 确实修复了异常。我第一次看到它是在这篇关于使用 Delphi 制作 XLL 的有用文章中使用的。这是最相关的报价:
“在 Delphi 中,加载项的最大绊脚石是堆栈上返回地址之后的额外参数。每次调用 Excel 时都会免费提供。我从来没有发现它包含什么,但只要你把它扔掉, 您的加载项将正常工作。添加行 asm pop variable, end; 在每次调用后,其中变量可以是任何全局、局部或对象变量,至少 4 字节长-整数很好。重复-这必须是包含在每次 Excel4v 调用之后。否则,您正在构建一个定时炸弹。”
基本上我想了解实际发生了什么,以及为什么。什么可能导致 Win32 函数返回“堆栈上的返回地址之后的额外参数”,这实际上意味着什么?
是否有另一种方法来解决这个问题,例如使用不同的编译器选项或声明函数的不同方式?
调用“asm pop sink; end;”有什么风险吗?每次调用 Excel4v 后...?它似乎工作正常,但是,由于我不明白发生了什么,感觉有点危险......