Delphi调用WinC编写的DLL问题?(100分)

  • 主题发起人 主题发起人 mrzj
  • 开始时间 开始时间
M

mrzj

Unregistered / Unconfirmed
GUEST, unregistred user!
C语言Dll文件,文件名cdll.dll<br>extern "C" __declspec(dllexport) char * GetMemberSum(LPTSTR vMemberName);<br>extern "C" __declspec(dllexport) char * GetMemberSum(LPTSTR vMemberName)<br>{ <br>return vMemberName;<br>} <br><br>Delphi主程序,运行下面程序后,返回结果是对的,但是马上就报错,什么原因,请指点!<br>unit testMain;<br>interface<br>uses<br>&nbsp; Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,<br>&nbsp; StdCtrls;<br>type<br>&nbsp; TForm1 = class(TForm)<br>&nbsp; &nbsp; Button1: TButton;<br>&nbsp; &nbsp; procedure Button1Click(Sender: TObject);<br>&nbsp; private<br>&nbsp; &nbsp; { Private declarations }<br>&nbsp; public<br>&nbsp; &nbsp; { Public declarations }<br>&nbsp; end;<br>var<br>&nbsp; Form1: TForm1;<br>&nbsp; function GetMemberSum(vMemberName: String) : PChar; stdcall;<br>implementation<br>&nbsp; function GetMemberSum; external 'cdll.DLL' name 'GetMemberSum';<br>{$R *.DFM}<br>procedure TForm1.Button1Click(Sender: TObject);<br>var<br>&nbsp; s:PChar;<br>begin<br>&nbsp; s:=GetMemberSum('TestStr');<br>&nbsp; showmessage(s
代码:
);<br>end;<br>end.
 
函数声明改为: GetMemberSum(vMemberName: PChar) : PChar; stdcall;<br>
 
Delphi做了如下更正,返回的结果是正确的,可是出现错误提示'access violation at<br>0x0012f6fd: write of address 0x00000000'这样的错误<br>
代码:
<br>var<br>&nbsp; Form1: TForm1;<br>&nbsp; function GetMemberSum(vMemberName: PChar) : PChar; stdcall;<br>implementation<br>&nbsp; function GetMemberSum; external 'JasmineDLL.DLL' name 'GetMemberSum';<br>{$R *.DFM}<br>procedure TForm1.Button1Click(Sender: TObject);<br>var<br>&nbsp; s:PChar;<br>&nbsp; p:PChar;<br>begin<br>&nbsp; GetMem(p,1024);<br>&nbsp; strPCopy(p,'N020010320010');<br>&nbsp; s:=GetMemberSum(p);<br>&nbsp; showmessage(s);<br>&nbsp; FreeMem(p);<br>end;<br>
 
&nbsp;FreeMem(p);错误,你不能释放DLl中的内存。<br>
 
我跟踪看了一下,这是不是Delphi调用C的DLL的一个Bug呀,我按下面的写法就可以了<br>&nbsp; GetMem(p,1024);<br>&nbsp; strPCopy(p,'N020010320010');<br>&nbsp; s:=GetMemberSum(p);<br>&nbsp; asm<br>&nbsp; &nbsp; pop eax;<br>&nbsp; end;<br>&nbsp; showmessage(s);<br>&nbsp; FreeMem(p);<br>在我跟踪时发现调用GetMemberSum(p)之后,stack居然不平衡了,我用了一句Pop eax 是保<br>证stack的平衡的,在我这里测试通过!<br>
 
O,是调用约定搞错了,你用 extern "C" 声明的,在Delphi 中声明要用cdecl 将<br>function GetMemberSum(vMemberName: PChar) : PChar; stdcall;<br>而为<br>function GetMemberSum(vMemberName: PChar) : PChar; cdecl;就行了,现在stack就平<br>衡了!:)!<br><br>
 
qiya水平可真高,在向你请教一下<br>stdcall;<br>cdecl;<br>的区别,还望告之,谢谢!<br><br>
 
&gt;&gt;mrzj<br>不要笑话我了,大家共同学习<br>stdcall 和 cdecl 的区别在于调用函数时压入stack的参数是由谁来移除,对于stdcall<br>它是在被调用的函数中移去参数,保证stack的平衡,而cdecl则由调用者移去,对于这种<br>指示符主要用在函数中有不固定参数的情况下,像printf!<br>详细的说明Delphi help 中有的!
 

Similar threads

I
回复
0
查看
893
import
I
S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
I
回复
0
查看
650
import
I
后退
顶部