请看这个dll调用窗体有什么错??很急。(100分)

  • 主题发起人 主题发起人 777
  • 开始时间 开始时间
7

777

Unregistered / Unconfirmed
GUEST, unregistred user!
//dll:
library Project1;

{ 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
SysUtils,
Classes,
Windows,
Messages,
Unit1 in 'Unit1.pas' {Form1};

{$R *.RES}
exports
CallMyForm;

begin

end.
//dll中的unit:
unit Unit1;

interface

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

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

var
Form1: TForm1;
function CallMyForm(hd:Thandle;caption:string):boolean
stdcall;
implementation

{$R *.DFM}
function CallMyForm(hd:Thandle;caption:string):boolean
stdcall;
var aa:Tform1;
begin
application.handle:=hd;
aa:= Form1.Create(application);
with aa do
begin
Caption:=caption;
ShowModal;
end;
aa.Free;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
Close;
end;
end.
=======================//调用dll:
unit Unit11;

interface

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

type
Ta = function(hd:Thandle;caption:string):boolean
stdcall;
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
var hr:Thandle;
pp:Ta;
begin
hr:=loadlibrary('Project1.dll');
if hr=0 then showmessage('dll false!')
else
begin
@pp:=GetProcAddress(hr,'CallMyForm');
if pp(hr,'abc') then exit;
end

freelibrary(hr);
end;

end.

 

if pp(hr,'abc') then exit;
~~~~~
改为application.handle
 
又是 Sharemem 的问题,在主 exe 和 dll 之间传递 string 时,exe 和 dll 的工程文件
中的 Uses 子句都必须第一个引用 Sharemem 单元。dll 工程中自动生成的注释不是说得
很清楚了吗?而且应这样调用:if pp(Application.Handle,'abc') then exit;
/dll project1.dpr
library Project1;
uses Sharemem, ...;

//exe project2.dpr
program Project2;
uses Sharemem, ...;
 
在function CallMyForm(hd:Thandle;caption:string):boolean
stdcall;函数中

aa:= Form1.Create(application)
是多余的,删掉,将aa换成form1,
 
TO:bbkxjy
还是不行错误提示是这样的:
Access Violation at address 010DEFC1 in mudule 'Project1.dll'.Read of
address 00000000
 
1. var
Form1: TForm1;
这句可以不要
2.aa:= Form1.Create(application);应为aa:=tform1.create(application)
也可改成create(nil)试试
3.参数还是最好不要用string,用pchar试试
 
还出错大概是因为 dll 中 Application 的 Handle 没有还原。试试改一下dll中函数:
function CallMyForm(hd:Thandle;Acaption:string):boolean
stdcall;
var
aa:Tform1;
OldHandle: THandle;
begin
OldHandle := Application.Handle;
try
Application.Handle:=hd;
aa:= TForm1.Create(Application);
with aa do
begin
Caption := Acaption
//原来两个 Caption 分不清
ShowModal;
end;
aa.Free;
finally
Application.Handle := OldHandle;
end;
end;
 
var
Form1: TForm1;
没有用去掉它
Caption:=caption;//这是啥意思
改为Caption:=ACaption;//不要重名

拜托你应该引用ShareMem在uses的第一个位置
否则你只能用pchar类型
看到下面的说明了吗
{ 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. }

我用下面代码
var
DLLForm: TDllForm;
begin
Application.Handle := AHandle;
DLLForm := TDLLForm.Create(Application)

try
DLLForm.Caption := ACaption;//ACaption:pchar;
DLLForm.ShowModal;
finally
DLLForm.Free;
end;
end;
 
唉,用各位的方法都试了,还是那个错。

Access Violation at address 010DEFC1 in mudule 'Project1.dll'.Read of
address 00000000

不会是我机子的问题吧。Delphi+Win2000
 
最好说明是做什么操作时出的错,或把你现在修改后的代码再贴出来。
 
to bbkxjy:
非常感谢你,和其它热心人此问题已搞定。犯了一个极其低下的错误:

aa:= Form1.Create(application);这里应改成
~~~~~
aa:= TForm1.Create(application);
呵呵。发分了。
 
不过,我不声名ShareMem,传递string也行不知为什么?
 
主程序中初始化的 string,其空间由主程序中的 MemoryManager 分配,传给 Dll,增加了
对该 string 的引用计数,如果最后清理释放空间时还是由主程序中的 MemoryManager 来
处理时,就不会出错。如:
主程序中
a)
var
str: string;
...
str := 'aaaa';
b) LoadLibrary 显式加载 dll
c) 调用 dll 中函数,传递 str 给该函数
d) FreeLibrary 显式卸载 dll
...
这样子就符合上面的条件,应该不会出错。如 dll 中的 string 传给主程序,就不行了。
 
我觉的都是String惹的祸,我曾经无数次到在他的脚下。虽然它好用,但却没有PCHAR安全。
 
后退
顶部