静态调用DLL出错.........
DLL工程的代码:(dgull.dll)
(uses
ShareMem,
SysUtils,
Classes,
Windows;)
Function GetSystemDirectory: String;Stdcall; //得到系统目录
Var
pcSystemDirectory: PChar;
dwSDSize: DWORD;
Begin
dwSDSize:=MAX_PATH+1;
GetMem(pcSystemDirectory, dwSDSize);
Try
If Windows.GetSystemDirectory(pcSystemDirectory, dwSDSize) <> 0 Then
Result:=pcSystemDirectory;
Finally
FreeMem(pcSystemDirectory);
End;
End;
调用的代码:
Function GetSystemDirectory: String;Stdcall; external 'dgull.dll ';
procedure TForm1.Button1Click(Sender: TObject);
begin
showmessage(GetSystemDirectory);
end;
*****
问题是,第一次点击Button一切正常,结果也对,可是第二次点击Button是出现错误:
存取地址***违例发生在模块 "ntdll.dll "中**********
怎么解决?是不是GetSystemDirectory函数的事?
[解决办法]
1、DLL:
library dgull;
{ Important note about DLL memory management: ShareMem must be the
first unit in your library 's USES clause AND your project 's (select
Project-View Source) USES clause if your DLL exports any procedures or
functions that pass strings as parameters or function results. This
applies to all strings passed to and from your DLL--even those that
are nested in records and classes. ShareMem is the interface unit to
the BORLNDMM.DLL shared memory manager, which must be deployed along
with your DLL. To avoid using BORLNDMM.DLL, pass string information
using PChar or ShortString parameters. }
uses
ShareMem,
SysUtils,
Classes,
Windows;
Function GetSystemDirectory: PChar; Stdcall; export; //得到系统目录
Var
pcSystemDirectory: PChar;
dwSDSize: DWORD;
Begin
dwSDSize:=MAX_PATH+1;
GetMem(pcSystemDirectory, dwSDSize);
Try
If Windows.GetSystemDirectory(pcSystemDirectory, dwSDSize) <> 0 Then
Result:=pcSystemDirectory;
Finally
FreeMem(pcSystemDirectory);
End;
End;
exports
GetSystemDirectory index 1 name 'GetSystemDirectory ' resident;
begin
end.
---------------------------
2、EXE:
...
var
Form1: TForm1;
implementation
{$R *.dfm}
Function GetSystemDirectory: PChar; Stdcall; external 'dgull.dll ';
procedure TForm1.Button1Click(Sender: TObject);
begin
showmessage(StrPas(GetSystemDirectory));
end;
[解决办法]
1.不要使用STRING,要使用PCHAR。
2.返回值一般来说只使用定长结构,不要传递变长字符串、数组。
3.PCHAR通过参数返回,调用前开辟足够空间,并传递空间长度给函数,函数确认空间长度,不要溢出。当空间不足,一般用布尔类型返回成功标志,或者用整型返回值通知调用者空间需求。
请参考WINDOWS API函数,看看Microsoft是怎么写API函数的。