小的不太熟悉DLL,熟悉DLL的人看看这个错误在哪里? ( 积分: 100 )

  • 主题发起人 主题发起人 阿群
  • 开始时间 开始时间

阿群

Unregistered / Unconfirmed
GUEST, unregistred user!
DLL代码如下:
library Login;

{ 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,
Windows,
Forms,
Controls,
MConnect,
SConnect,
//DBClient,
Classes,
LoginU in '../SysSetup/LoginU.pas' {frmLogin};

{$R *.res}

Function ShowLoginForm(app:TApplication;SocketCon:TSocketConnection;IniPath:string;var IsTrial:boolean;
var UserName,usepawd:LPSTR):boolean;stdcall;
var
p:^LongInt;
begin
p:=@(Application.MainForm);
p^:=LongInt(app.MainForm);
Frmlogin := TFrmlogin.Create(app);
Frmlogin.SocketCon:=SocketCon;
Frmlogin.IniPath:=IniPath;
if Frmlogin.ShowModal = mrOK then
begin
IsTrial:=Frmlogin.IsTrial;
UserName:=pchar(FrmLogin.UserName);
usepawd:=pchar(FrmLogin.usepawd);
Result := true;
end
else
Result := False;
end;

exports
ShowLoginForm;

begin
end.

调用DLL代码如下:
var
BaseDataDMF: TBaseDataDMF;
implementation
uses GlobalU;
Function ShowLoginForm(app:TApplication;SocketCon:TSocketConnection;IniPath:string;var IsTrial:boolean;var UserName,usepawd:LPSTR):boolean;stdcall;external 'Login.dll';
{$R *.dfm}
function TBaseDataDMF.Login: Boolean;
var IsTrial:boolean;
UserName,usepawd:LPSTR;
begin
result:=ShowLoginForm(Application,SocketConnection,extractfilepath(application.ExeName),IsTrial,UserName,usepawd);
if result then
begin
GlobalData.IsTrial:=IsTrial;
GlobalData.UserName:=String(UserName);
GlobalData.usepawd:=String(usepawd);
end;
end;
问题是:第一次调用Login不会有问题,第二次在程序中调用的时候出现访问login.dll的无效地址错误,不解?
 
DLL代码如下:
library Login;

{ 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,
Windows,
Forms,
Controls,
MConnect,
SConnect,
//DBClient,
Classes,
LoginU in '../SysSetup/LoginU.pas' {frmLogin};

{$R *.res}

Function ShowLoginForm(app:TApplication;SocketCon:TSocketConnection;IniPath:string;var IsTrial:boolean;
var UserName,usepawd:LPSTR):boolean;stdcall;
var
p:^LongInt;
begin
p:=@(Application.MainForm);
p^:=LongInt(app.MainForm);
Frmlogin := TFrmlogin.Create(app);
Frmlogin.SocketCon:=SocketCon;
Frmlogin.IniPath:=IniPath;
if Frmlogin.ShowModal = mrOK then
begin
IsTrial:=Frmlogin.IsTrial;
UserName:=pchar(FrmLogin.UserName);
usepawd:=pchar(FrmLogin.usepawd);
Result := true;
end
else
Result := False;
end;

exports
ShowLoginForm;

begin
end.

调用DLL代码如下:
var
BaseDataDMF: TBaseDataDMF;
implementation
uses GlobalU;
Function ShowLoginForm(app:TApplication;SocketCon:TSocketConnection;IniPath:string;var IsTrial:boolean;var UserName,usepawd:LPSTR):boolean;stdcall;external 'Login.dll';
{$R *.dfm}
function TBaseDataDMF.Login: Boolean;
var IsTrial:boolean;
UserName,usepawd:LPSTR;
begin
result:=ShowLoginForm(Application,SocketConnection,extractfilepath(application.ExeName),IsTrial,UserName,usepawd);
if result then
begin
GlobalData.IsTrial:=IsTrial;
GlobalData.UserName:=String(UserName);
GlobalData.usepawd:=String(usepawd);
end;
end;
问题是:第一次调用Login不会有问题,第二次在程序中调用的时候出现访问login.dll的无效地址错误,不解?
 
p指针不用释放吗?或者在用的时候new一下.
 
TFrmlogin不可以被创建了2次
 
borland的声明里不是写清楚了吗?如果传递string参数或返回string型值就要在dll单元和引用单元的uses子句的第一行写ShareMem,除非你把参数改为Pchar或ShortString。
 
thank newsmile,上面的是可以了,可是我又加了个新的功能,写法跟上面的差不多,但是如果运行上面的代码后再运行新功能时也报同样的错误,如果单独运行新功能则正常,不知错在哪里?小的不才,望告之,新功能代码如下:
DLL代码:
library SetPassword;

{ 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,
Controls,
Classes,
Windows,
ShareMem,
Forms,
DBClient,
passwordU in 'passwordU.pas' {passwordF};
{$R *.res}
Function ShowPassWordForm(app:TApplication;CommConnect:TClientDataSet;VerKnd:smallint;
OperatorManId:String;var usepawd:LPSTR):boolean;stdcall;
var
p:^LongInt;
begin
p:=@(Application.MainForm);
p^:=LongInt(app.MainForm);
passwordF:= TpasswordF.Create(app);
passwordF.CommConnect:=CommConnect;
passwordF.VerKnd:=VerKnd;
passwordF.OperatorManId:=OperatorManId;
passwordF.usepawd:=String(usepawd);
if passwordF.ShowModal = mrOK then
begin
usepawd:=pchar(passwordF.usepawd);
Result := true;
end
else
Result := False;
end;

exports
ShowPassWordForm;

begin
end.


unit passwordU;

interface

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

type
TpasswordF = class(TForm)
Panel_fundus: TPanel;
GroupBox1: TGroupBox;
Label2: TLabel;
Label3: TLabel;
Label5: TLabel;
Edit2: TEdit;
Edit3: TEdit;
Edit1: TEdit;
BitBtn1: TBitBtn;
BitBtn2: TBitBtn;
procedure BitBtn1Click(Sender: TObject);
procedure BitBtn2Click(Sender: TObject);
procedure FormClose(Sender: TObject
var Action: TCloseAction);
private
{ Private declarations }
public
{ Public declarations }
VerKnd:smallint;//0为ACCESS,1为SqlServer
usepawd,OperatorManId:String;
CommConnect:TClientDataSet;
end;

var
passwordF: TpasswordF;

implementation

uses dxCommonU;
{$R *.dfm}

procedure TpasswordF.BitBtn1Click(Sender: TObject);
var
a1,a2,a3:string;
SQLexp:string;
TmpCD:TClientDataSet;
begin
SQLexp:='';
a1:=trim(edit1.text);
a2:=trim(edit2.text);
a3:=trim(edit3.text);
if usepawd<>a1 then messagebox(GetActiveWindow,'原口令不正确','提示',MB_OK)
Else
if a2='' then messagebox(GetActiveWindow,'新口令不能为空','提示',MB_OK)
Else
If a2<>a3 then messagebox(GetActiveWindow,'新口令和新口令确认不一致','提示',MB_OK)
Else
try
TmpCD:=TClientDataSet.Create(nil);
SetConnectClientDataSet(CommConnect,TmpCD);//赋予remoteserver和providername属性
{$IFDEF ACCESS}
{$ELSE}
{$ENDIF}
if VerKnd=0 then
begin
SQLexp:='update Operator set Password='+quotedstr(a2)+' where OperatorId='+OperatorManId;
try
ClientDataSetExcute(TmpCD,SQLexp);
messagebox(GetActiveWindow,'修改密码成功!','提示',MB_OK);
usepawd:=a2;
ModalResult:=mrOk;
except
messagebox(GetActiveWindow,'修改密码失败!','提示',MB_OK);
end;
end
else
begin
SQLexp:='declare @Fstate int,@msg varchar(100)'+#13#10+
'select @Fstate=0,@msg='+quotedstr('修改密码成功!')+#13#10+
'update Operator set Password='+quotedstr(a2)+' where OperatorId='+OperatorManId+#13#10+
'if @@ERROR<>0'+#13#10+
'select @Fstate=-6,@msg='+quotedstr('修改密码失败!')+#13#10+
'select state=@Fstate,mesg=@msg';
ClientDataSetExcute(TmpCD,SQLexp);
if TmpCD.FieldByName('state').AsInteger>=0 then
Begin
messagebox(GetActiveWindow,pchar(TmpCD.FieldByName('mesg').Asstring),'提示',MB_OK);
usepawd:=a2;
ModalResult:=mrOk;
End Else messagebox(GetActiveWindow,pchar(TmpCD.FieldByName('mesg').Asstring),'提示',MB_OK);
end;
finally
TmpCD.Free;
End;
end;

procedure TpasswordF.BitBtn2Click(Sender: TObject);
begin
ModalResult:=mrCancel;
end;

procedure TpasswordF.FormClose(Sender: TObject
var Action: TCloseAction);
begin
Action:=caFree;
end;

end.
 
ShareMem要放在uses子句的第一行。主程序里也要ShareMem放在第一行。
 
newsmile,可以了,不过不知为何DLL中窗体的ICON图标和主程序的不一样,有什么办法让他们一样?
 
图标很简单^_^
在你的函数里面加一行就可以了。
Function ShowPassWordForm(app:TApplication;CommConnect:TClientDataSet;VerKnd:smallint;
OperatorManId:String;var usepawd:LPSTR):boolean;stdcall;
var
p:^LongInt;
begin
p:=@(Application.MainForm);
p^:=LongInt(app.MainForm);
passwordF:= TpasswordF.Create(app);
//这里加一行
passwordF.Icon.assign(app.Icon);
 
晶晶是位小姑娘吧!如果也是做程序的就不简单啊!不过你说的方法可不行哦!
 
小的实在不明白如下代码错在哪里?
DLL代码:
library BaseInfo;
uses
ShareMem,
SysUtils,
Forms,
Controls,
dxCommonU,
DBClient,
Classes;

procedure MatrInput(app:TApplication;ConnectCD:TClientDataSet;RoleId:integer;UserTrueName,cap,menuname:string;IsTrial:boolean);
{.......}

exports
MatrInput;

begin
end.

调用DLL公共单元:
unit CallDllU;

interface
uses
ShareMem,SysUtils,Classes,DBClient,forms,MConnect, SConnect, StrUtils,windows, StdCtrls;

procedure MatrInput(app:TApplication;ConnectCD:TClientDataSet;RoleId:integer;UserTrueName,cap,menuname:string;
IsTrial:boolean);stdcall;external 'BaseInfo.dll';
implementation

end.
在界面里调用此过程时还未进入到DLL过程即报Error Description: Access violation at address 01074D54 in module 'BaseInfo.dll'. Read of address FFFFFFF9,各位高人请指教一二,感激不尽!
 
你的主程序里有写sharemem没有?
 
procedure MatrInput(app:TApplication;ConnectCD:TClientDataSet;RoleId:integer;UserTrueName,cap,menuname:string;
IsTrial:boolean);stdcall;external 'BaseInfo.dll';
这个函数在DLL中有没有申明后加上stdcall?
 
后退
顶部