本人刚学dll,大家帮忙看看。
program Project1;uses
Forms, Dialogs, Classes,
Unit1 in 'Unit1.pas' {Form1};function Login(AHandle: THandle; ACaption: ShortString): Boolean; external 'LoginDll.dll' name 'Login';
function GetUserName:PChar; external 'LoginDll.dll' name 'GetUserName';{$R *.res}
var
a:PChar;begin
a:='abc';
Application.Initialize;
if Login(Application.Handle, a) then begin
showmessage('成功');
a:=GetUserName; // 这有问题不能编译。注释掉可以编译
end
else begin
showmessage('失败');
Application.Terminate;
end; Application.CreateForm(TForm1, Form1);
Application.Run;
end.
library LoginDll;
uses
SysUtils,
Classes,
LoginFrm in 'LoginFrm.pas' {LogInForm};{$R *.res}exports
Login,
GetUserName,
GetPassword,
GetProject;
begin
end.unit LoginFrm;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, jpeg, IniFiles;type
TLogInForm = class(TForm)
btnOk: TButton;
btnCancel: TButton;
Image1: TImage;
Label2: TLabel;
lblUserId: TLabel;
Label1: TLabel;
lblProjCode: TLabel;
EditUserId: TEdit;
EditPassWd: TEdit;
EditProjCode: TEdit;
procedure btnOkClick(Sender: TObject);
procedure FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end; function Login(AHandle: THandle; ACaption: String): boolean; stdcall;
function GetUserName:PChar; stdcall;
function GetPassword:PChar; stdcall;
function GetProject :PChar; stdcall;var
Check: boolean;
FUserName:PChar;
FPassword:PChar;
FProject :PChar;implementation{$R *.dfm}procedure TLogInForm.btnOkClick(Sender: TObject);
begin
if (EditUserId.text='') then begin
MessageDlg('用户代码不能为空!', mtError, [mbOk], 0);
editUserID.SetFocus;
Exit;
end
else if (EditPassWd.text='') then begin
MessageDlg('用户密码不能为空!', mtError, [mbOk], 0);
editPassWd.SetFocus;
Exit;
end
else if (EditProjCode.text='') then begin
MessageDlg('项目代码不能为空!', mtError, [mbOk], 0);
editProjCode.SetFocus;
Exit;
end
else begin
FUserName:=PCHAR(editUserid.Text);
FPassword:=PCHAR(EditPassWd.Text);
FProject:=PCHAR(EditProjcode.text);
Check:=True;
ModalResult:=mrOK;
end;
end;procedure TLogInForm.FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
case key of
VK_RETURN : btnOkClick(self);
VK_ESCAPE : begin
ModalResult:=mrCancel;
end;
end;
end;function Login(AHandle: THandle; ACaption: String): boolean;
var
LogInForm: TLogInForm;
begin
Check := False;
Application.Handle := AHandle;
LoginForm := TLoginForm.Create(Application);
try
LoginForm.Caption := ACaption; // 这也有问题,标题为乱码
LoginForm.ShowModal;
//返回给调用本dll的应用程序判断
Result:=Check;
finally
LoginForm.Free;
end;
end;procedure TLogInForm.FormCreate(Sender: TObject);
var
IniFile:TIniFile;
begin
IniFile:=TIniFile.Create(ExtractFilePath(Application.ExeName)+'Login.ini');
EditUserID.Text:=IniFile.ReadString('LogInfo', 'userID', '');
EditProjCode.Text:=IniFile.ReadString('LogInfo', 'projectID', '');
IniFile.Free;
end;function GetUserName:PChar;
begin
Result:=FUserName;
end;function GetPassword:Pchar;
begin
Result:=FPassword;
end;function GetProject:PChar;
begin
Result:=FProject;
end;end.
program Project1;uses
Forms, Dialogs, Classes,
Unit1 in 'Unit1.pas' {Form1};function Login(AHandle: THandle; ACaption: ShortString): Boolean; external 'LoginDll.dll' name 'Login';
function GetUserName:PChar; external 'LoginDll.dll' name 'GetUserName';{$R *.res}
var
a:PChar;begin
a:='abc';
Application.Initialize;
if Login(Application.Handle, a) then begin
showmessage('成功');
a:=GetUserName; // 这有问题不能编译。注释掉可以编译
end
else begin
showmessage('失败');
Application.Terminate;
end; Application.CreateForm(TForm1, Form1);
Application.Run;
end.
library LoginDll;
uses
SysUtils,
Classes,
LoginFrm in 'LoginFrm.pas' {LogInForm};{$R *.res}exports
Login,
GetUserName,
GetPassword,
GetProject;
begin
end.unit LoginFrm;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, jpeg, IniFiles;type
TLogInForm = class(TForm)
btnOk: TButton;
btnCancel: TButton;
Image1: TImage;
Label2: TLabel;
lblUserId: TLabel;
Label1: TLabel;
lblProjCode: TLabel;
EditUserId: TEdit;
EditPassWd: TEdit;
EditProjCode: TEdit;
procedure btnOkClick(Sender: TObject);
procedure FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end; function Login(AHandle: THandle; ACaption: String): boolean; stdcall;
function GetUserName:PChar; stdcall;
function GetPassword:PChar; stdcall;
function GetProject :PChar; stdcall;var
Check: boolean;
FUserName:PChar;
FPassword:PChar;
FProject :PChar;implementation{$R *.dfm}procedure TLogInForm.btnOkClick(Sender: TObject);
begin
if (EditUserId.text='') then begin
MessageDlg('用户代码不能为空!', mtError, [mbOk], 0);
editUserID.SetFocus;
Exit;
end
else if (EditPassWd.text='') then begin
MessageDlg('用户密码不能为空!', mtError, [mbOk], 0);
editPassWd.SetFocus;
Exit;
end
else if (EditProjCode.text='') then begin
MessageDlg('项目代码不能为空!', mtError, [mbOk], 0);
editProjCode.SetFocus;
Exit;
end
else begin
FUserName:=PCHAR(editUserid.Text);
FPassword:=PCHAR(EditPassWd.Text);
FProject:=PCHAR(EditProjcode.text);
Check:=True;
ModalResult:=mrOK;
end;
end;procedure TLogInForm.FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
case key of
VK_RETURN : btnOkClick(self);
VK_ESCAPE : begin
ModalResult:=mrCancel;
end;
end;
end;function Login(AHandle: THandle; ACaption: String): boolean;
var
LogInForm: TLogInForm;
begin
Check := False;
Application.Handle := AHandle;
LoginForm := TLoginForm.Create(Application);
try
LoginForm.Caption := ACaption; // 这也有问题,标题为乱码
LoginForm.ShowModal;
//返回给调用本dll的应用程序判断
Result:=Check;
finally
LoginForm.Free;
end;
end;procedure TLogInForm.FormCreate(Sender: TObject);
var
IniFile:TIniFile;
begin
IniFile:=TIniFile.Create(ExtractFilePath(Application.ExeName)+'Login.ini');
EditUserID.Text:=IniFile.ReadString('LogInfo', 'userID', '');
EditProjCode.Text:=IniFile.ReadString('LogInfo', 'projectID', '');
IniFile.Free;
end;function GetUserName:PChar;
begin
Result:=FUserName;
end;function GetPassword:Pchar;
begin
Result:=FPassword;
end;function GetProject:PChar;
begin
Result:=FProject;
end;end.
能这么赋值吗?UP一下
begin
getmem(result,length(fusername));
strpcopy(result,fusername);
// Result:=FUserName;
end;
把GetUserName函数改一下
funcation GetUserName:PChar;stdcall;
begin
...
end;
另外:
function Login(AHandle: THandle; ACaption: String): boolean;
var
LogInForm: TLogInForm;
begin
Check := False;
Application.Handle := AHandle;
LoginForm := TLoginForm.Create(Application);
try
LoginForm.Caption := ACaption; // 这也有问题,标题为乱码
LoginForm.ShowModal;
//返回给调用本dll的应用程序判断
Result:=Check;
finally
LoginForm.Free;
end;
end;
你的ACaption不可以用String的,那是Delphi解释的,你要用Windows标准的字符串,或者用PChar
begin
GetMem(Result, Length(FUserName));
StrCopy(Result, FUserName);
end;这样也不行啊
Inc(Size); {Add room for null character}
GetMem(Buffer, Size); {Creates Buffer dynamic variable}
Edit1.GetTextBuf(Buffer,Size); {Puts Edit1.Text into Buffer}
Edit2.Text := StrPas(Buffer); {Converts Buffer to a Pascal-style string}
FreeMem(Buffer, Size);{Frees memory allocated to Buffer}
LoginForm.Caption := ACaption;
的ACaption是String的,所以会有乱码因为Dll是不认String的
,你应该在Uses语句中加上Sharemem,工程中的Uses中叶加上,并放在第一个就行了,因为你传的是String型,这是Delphi的解释
{ 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. }
function Login(AHandle: THandle; ACaption: ShortString): Boolean; external 'LoginDll.dll' name 'Login';
function GetUserName:PChar; external 'LoginDll.dll' name 'GetUserName';改为:
function Login(AHandle: THandle; ACaption: ShortString): Boolean;stdcall; external 'LoginDll.dll' name 'Login';
function GetUserName:PChar; stdcall;external 'LoginDll.dll' name 'GetUserName';
两个都加上stdcall
1、函数的参数传递问题,编写及调用都要加stdcall;
2、尽量避免使用String类型参数,在使用到时,要在编写调用的单中加入ShareMem引用。
第2个问题是一个头痛的问题,我用的是TStringList参数,怎么也不能正常调用,现在正在
找解决方法。
function GetUserName:PChar; stdcall;
function GetPassword:PChar; stdcall;
function GetProject :PChar; stdcall;这四句去掉后面的stdcall;
function Login(AHandle: THandle; ACaption: Pchar): boolean;
var
LogInForm: TLogInForm;
begin
Getmem(ACaption,30);
Check := False;
Application.Handle := AHandle;
LoginForm := TLoginForm.Create(Application);
try
LoginForm.Caption := string(ACaption); // 这也有问题,标题为乱码
LoginForm.ShowModal;
//返回给调用本dll的应用程序判断
Result:=Check;
finally
LoginForm.Free;
freemem(ACaption,30);
end;
end;