我变得疯了.
我是初学者,我想制作我的第一个DLL.我遵循了这个指南:
http://www.tutorialspoint.com/dll/dll_delphi_example.htm
我想设置一个关于程序版本的文本信息,并在我想要的时候阅读它,所以通过主应用程序将它显示给用户.这只是保持对DLL的信心的一个例子,我已经知道有很多其他方法可以实现这一点.
现在我试图从这样的DLL中读取变量"versione":
library Clientdll;
uses SysUtils, Classes, Dialogs;
{$R *.res}
function Versione(var messaggio, versione: String):string; export; stdcall;
begin
versione:='Nessun dato ricavato. Valore di chiamata alla DLL errato!';
if messaggio='chiama' then versione:='v4.0.0 build 31';
end;
exports versione;
begin
end.
Run Code Online (Sandbox Code Playgroud)
在主应用程序中我写了这个:
[...]
implementation
uses unit2;
{$R *.dfm}
function Versione(var messaggio, versione:string):string; stdcall; external 'Clientdll.dll'
Run Code Online (Sandbox Code Playgroud)
[...]
现在我说'好吧,我只是要调用DLL而这就是......'.所以:
procedure TForm1.Button1Click(Sender: TObject);
var x, y:string;
begin
x:='chiama';
Versione(x,y);
showmessage(y);
end;
Run Code Online (Sandbox Code Playgroud)
我可以在对话框中阅读v4.0.0 build 31,但是当我按OK时我收到此错误:
"无效的指针操作".
有任何想法吗?
我试着谷歌,但我的英语很差,一些答案很难理解,也有翻译工具!
不要String用作参数类型.在File->New->Other->Delphi Projects->DLL Wizard用于创建新DLL 时IDE生成的注释中清楚地解释了这一点:
{关于DLL内存管理的重要说明:如果您的DLL导出任何将字符串作为参数或函数结果传递的过程或函数,则ShareMem必须是库的USES子句和项目(选择项目 - 视图源)USES子句中的第一个单元.这适用于传递到DLL或从DLL传递的所有字符串 -即使是嵌套在记录和类中的字符串.ShareMem是BORLNDMM.DLL共享内存管理器的接口单元,必须与DLL一起部署.要避免使用BORLNDMM.DLL,请使用PChar或ShortString参数传递字符串信息.}
此外,使用Delphi字符串意味着您的DLL函数不能从其他语言(如C)调用.
您还应该期望调用应用程序为您提供放置结果的内存(以及一个长度参数,告诉您内存缓冲区的大小).
这是一个带有单个函数的Delphi dll的最小(相当无用)示例,以及一个调用它的测试应用程序.(正如我所说,DLL是没有意义的.任何实际的DLL都应该设计为将功能代码放在它自己的单元而不是项目文件中.)
示例DLL源:
library SimpleTest;
{ 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;
{$R *.res}
// Parameters:
// arg: Argument that indicates whether this is a test or
// something else, so we know which value to return
// Buffer: The space in which to place the result
// Len: The length of the buffer provided
function TestDLL(const arg: PChar; const Buffer: PChar;
const Len: Integer): Boolean; stdcall;
begin
// Make sure we use the Len parameter, so we don't overflow
// the memory we were given. StrLCopy will copy a maximum of
// Len characters, even if the length of the string provided
// as the 'source' parameter is longer.
if arg = 'Test' then
StrLCopy(Buffer, 'Test result', Len)
else
StrLCopy(Buffer, 'Non-test result', Len);
Result := True;
end;
exports
TestDll;
begin
end.
Run Code Online (Sandbox Code Playgroud)
调用它的测试应用程序的表单:
unit DLLTestForm;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form4: TForm4;
implementation
{$R *.dfm}
function TestDLL(const arg: PChar; const Buffer: PChar; const Len: Integer): Boolean; stdcall;
external 'SimpleTest.dll';
procedure TForm4.Button1Click(Sender: TObject);
var
Parm1: String;
Parm2: String;
BuffLen: Integer;
begin
Parm1 := 'Test';
// Length of buffer (including null terminator) for DLL call
// Chosen arbitrarily - I know the DLL won't return more than 15 + the
// null. I'm pretending I don't, though, and allowing extra space. The
// DLL won't return more than 30 characters, even if it has more to say,
// because it uses StrLCopy to limit the result to Len characters.
BuffLen := 30;
// Allocate space for return value
SetLength(Parm2, BuffLen);
// Call the DLL with `Test` arg
if TestDLL(PChar(Parm1), PChar(Parm2), BuffLen) then
ShowMessage(Parm2);
// Call the DLL with a different parameter value
Parm1 := 'Other';
if TestDLL(PChar(Parm1), PChar(Parm2), BuffLen) then
ShowMessage(Parm2);
end;
end.
Run Code Online (Sandbox Code Playgroud)