静态调用DLL出错.........

luincnyou 2007-02-11 03:55:54
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函数的事?
...全文
256 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
luincnyou 2007-02-12
  • 打赏
  • 举报
回复
搞定~~~
luincnyou 2007-02-12
  • 打赏
  • 举报
回复
改了,不行啊.
应用程序全部代码:
Unit Unit1;

Interface

Uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

Type
TForm1=Class(TForm)
Button1: TButton;
Procedure Button1Click(Sender: TObject);
Private
{ Private declarations }
Public
{ Public declarations }
End;

Var
Form1: TForm1;

Implementation
{$R *.dfm}
Function GetSystemDirectory: String;Stdcall; external 'd.dll';


procedure TForm1.Button1Click(Sender: TObject);
begin
showmessage(GetSystemDirectory);
end;


End.
**********
DLL全部代码:
Library d;
Uses
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;


Exports
GetSystemDirectory;

Begin
End.
**********
第一次点击BUTTON一切正常,结果也没错,可是第二次点击提示什么存取地址***违例(ntdll.dll),第三次及以后就改为了d.dll(我的哪个dll)
郁闷啊~~~怎么回事?谢了!!!!
rangwoxiao 2007-02-11
  • 打赏
  • 举报
回复
同意老猫的看法
快乐老猫 2007-02-11
  • 打赏
  • 举报
回复
楼上的写法不安全,应该传递字符串空间长度给函数。
一切都要参考microsoft的格式。
lihuasoft 2007-02-11
  • 打赏
  • 举报
回复
Function GetSystemDirectory(var pcSystemDirectory : PChar) : boolean; Stdcall; export;
begin
result := False;
Try
If Windows.GetSystemDirectory(pcSystemDirectory, MaxInt)<>0 Then
Result := true;
except
result := false;
end;
end;
lihuasoft 2007-02-11
  • 打赏
  • 举报
回复
DLL返回String类型,本身就是不可取的。因为DLL不仅仅能用在Delphi编译的程序......
lihuasoft 2007-02-11
  • 打赏
  • 举报
回复
前面的代码我试验了。

你再试一下下面的:

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(var pcSystemDirectory : PChar) : boolean; Stdcall; export; //得到系统目录
begin
Try
If Windows.GetSystemDirectory(pcSystemDirectory, MaxInt)<>0 Then
Result := true;
except
result := false;
end;
end;


exports
GetSystemDirectory index 1 name 'GetSystemDirectory' resident;

begin
end.

======================================

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}
Function GetSystemDirectory(var pcSystemDirectory : PChar) : BOOLEAN; Stdcall; external 'dgull.dll';


procedure TForm1.Button1Click(Sender: TObject);
var
P : PChar;
begin
GetMem(P, MAX_PATH+1);
GetSystemDirectory(P);
showmessage(StrPas(P));
FreeMem(P);
end;

end.
luincnyou 2007-02-11
  • 打赏
  • 举报
回复
而且我是想保持string不变的,我的两个工程(dll,和应用程序)都在前面加了ShareMem,一切正常,就是退出时错误(204)
luincnyou 2007-02-11
  • 打赏
  • 举报
回复
to:lihuasoft,我就是照你的复制的,乱码....
madyak 2007-02-11
  • 打赏
  • 举报
回复
Try
If Windows.GetSystemDirectory(pcSystemDirectory, dwSDSize)<>0 Then
Result:=pcSystemDirectory;
Finally
FreeMem(pcSystemDirectory);//如果Result是PChar,这里释放内存是不合适的。返回的地址将会是无效的地址。
End;
lihuasoft 2007-02-11
  • 打赏
  • 举报
回复
注意,我主要改动了你代码的以下位置:

Dll 的 Function GetSystemDirectory: PChar; Stdcall;
~~~~~~~~

EXE 的

Function GetSystemDirectory: PChar; Stdcall; external 'dgull.dll';
~~~~~~~~

procedure TForm1.Button1Click(Sender: TObject);
begin
showmessage(StrPas(GetSystemDirectory));
~~~~~~~~
end;
快乐老猫 2007-02-11
  • 打赏
  • 举报
回复
1.不要使用STRING,要使用PCHAR。
2.返回值一般来说只使用定长结构,不要传递变长字符串、数组。
3.PCHAR通过参数返回,调用前开辟足够空间,并传递空间长度给函数,函数确认空间长度,不要溢出。当空间不足,一般用布尔类型返回成功标志,或者用整型返回值通知调用者空间需求。

请参考WINDOWS API函数,看看Microsoft是怎么写API函数的。
lihuasoft 2007-02-11
  • 打赏
  • 举报
回复
要不,你把我的代码复制下来,新建一个DLL试试吧。完全复制。EXE的代码,我只贴出了implementation下面的部分。OK?
luincnyou 2007-02-11
  • 打赏
  • 举报
回复
改回string类型,DLL和程序都引用ShareMem就正常了,可是关闭程序时出现Runtime error 204 at
****
lihuasoft 2007-02-11
  • 打赏
  • 举报
回复
呵,不是的,我在这里试验了的。仔细对照一下我的代码。
luincnyou 2007-02-11
  • 打赏
  • 举报
回复
结果好像是乱码
lihuasoft 2007-02-11
  • 打赏
  • 举报
回复
注意,我把DLL函数的返回值由String类型改为了PChar指针。相应的调用,及返回值转字符串StrPas的利用。
lihuasoft 2007-02-11
  • 打赏
  • 举报
回复
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;
luincnyou 2007-02-11
  • 打赏
  • 举报
回复
点第三次以后错误提示就变成了存取地址***违例发生在模块"borlndmm.dll"中**********

5,388

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧