在C中,特别是在Microsoft Excel 2007 XLL SDK附带的xlcall.h文件中,Excel4v定义为:
int pascal Excel4v(int xlfn,LPXLOPER operRes,int count,LPXLOPER opers[]);
在Delphi我正在使用:
function Excel4v(xlfn: Integer; operRes: LPXLOPER; count: Integer; opers: array of LPXLOPER): Integer; stdcall; external 'xlcall32.dll';
LPXLOPER是指向结构(在C中)或记录(在Delphi中)的指针.
我一直在做我在Delphi中声明C函数的功课(this excellent article是一个很好的帮助),我想我正在宣布Excel4v.但是,从Delphi代码调用该函数会导致异常(“访问违规……”是我一直看到的),除非后面跟着以下行:
asm pop sink; end;
其中“sink”在某处定义为整数.
我对组装没有任何线索……所以我没想办法用“asm pop sink; end;”来修复异常.但是“asm pop sink; end;”确实修复了异常.我第一次看到它在this useful article on making XLLs using Delphi中使用.这是最相关的引用:
“From Delphi the big stumbling block
with add-ins is the extra parameter
after the return address on the stack.
This comes free with every call to
Excel. I’ve never found out what it
holds,but so long as you throw it
away,your add-in will work fine. Add
the line asm pop variable,end; after
every call where variable can be any
global,local or object variable that
is at least 4 bytes long- integer is
fine. To repeat- THIS MUST BE INCLUDED
after every Excel4v call. Otherwise
you are constructing a time-bomb.”
基本上我想了解实际发生了什么,以及为什么.什么可能导致Win32函数返回“堆栈上的返回地址后的额外参数”,这实际上是什么意思?
可能有另一种解决方法,例如使用不同的编译器选项或声明函数的不同方式?
并且有什么风险可以称为“asm pop sink; end;”每次调用Excel4v后……?它看起来工作正常,但是,由于我不明白发生了什么,感觉有点危险……
解决方法
从引用的article,
This would indeed be a very nice
Syntax,but it is not the same as the
above array definition. Array-of
parameters are open array parameters.
They may look like any array,and they
do accept any array,but they get an
extra (hidden) parameter,which holds
the highest index in the array (the
High value). Since this is only so in
Delphi,and not in C or C++,you’d
have a real problem. (See also my
article on open arrays),since the
real number of parameters wouldn’t
match.
您将获得传递给函数的额外“最高数组索引”参数.这是一个int,当函数退出时必须清理它,这样你就不会遇到损坏的堆栈并崩溃.本文指出如何将数组传递给C函数.
就像是:
type PLPXLOPER = ^LPXLOPER;
并将PLPXLOPER作为最后一个参数传递.