VC里调用DELPHI编写的DLL要注意的!
今天在DFW上面看见有一个贴子是关于VC里面调用DELPHI编写的DLL,对于VC和DELPHI有一定自信的我,当然不过这样的拿分机会了。
贴子的大概内容是这样的,在DELPHI定义了这样一个函数并输出
myfunc(i:Integer
b:Byte
var Buffer:array of Word): Boolean
stdcall;
之后在VC里面定义函数类型
typedef BOOL (__stdcall *pMyfunc)(int, BYTE, WORD*);
调用代码是这样
HMODULE h= LoadLibrary("C://Program Files//Borland//Delphi7//Projects//project2.dll"
;
pMyfunc MyFunc=(pMyfunc)GetProcAddress(h,"myfunc"
;
WORD a[100];
memset(a, 0, sizeof(a));
a[0]= 1;
a[1]= 2;
a[2]= 3;
MyFunc(1, 2, a);
但是函数成功返回后却提示:
The value of ESP was not properly saved across a function call.This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.
经过研究,得出的解决的办法就是在VC里面这样定义函数类型
typedef BOOL (__stdcall *pMyfunc)(int, BYTE, WORD*, int);
多出一个参数int是数组的大小,所以调用时就要指出数组的大小
MyFunc(1, 2, a, sizeof(a)/sizeof(WROD));
下面是研究的过程。
根据出错提示和我的破解来看,一定是调用函数后栈不平衡了。至于具体原因就要再进一步研究。
我在Delphi调用了这个函数,并没有任何问题。所以我的直觉告诉我,一定和那个数组有关,之后我拿掉那个数组参数,在VC里调用一次,结果一切正常! 看来真的是数组参数的问题。但是为什么Delph里调用却没有问题呢?想来想去也想不出原因,看来只好在汇编里找答案了。在Delphi里调用myfunc的地方下了断点,
{调用函数的代码}
var
aw: array[0..99] of word;
//aw: array of word;
begin
//setlength(aw, 101);
myfunc(1, 2, aw);
//这里的反汇编对应静态数组的代码
004081FA 6A63 push $63
004081FC 6898A74000 push $0040a798
00408201 6A02 push $02
00408203 6A01 push $01
00408205 E82EFFFFFF call myfunc
//这里的反汇编对应动态数组的代码
004086E4 A198A74000 mov eax,[aw]
004086E9 E812BCFFFF call @DynArrayHigh
004086EE 50 push eax
004086EF A198A74000 mov eax,[aw]
004086F4 50 push eax
004086F5 6A02 push $02
004086F7 6A01 push $01
004086F9 E8E6FEFFFF call myfunc
可以很清楚的看到,我们的函数明明只定义了3个参数,却push了4个参数!而第4个函数根据静态数组的反汇编可以看出就是数组的长度!
所以在VC的函数定义要多定义一个参数,并把数组的长度传递给函数调用才会正常!
反思:原来自己对DELPHI的内部还不是很了解,还是菜菜一名,呵呵。