我想创建一个简单的程序,将Edit1.Text设置为" 6" (例如,但使用DLL - 这很重要)。这是代码: 单位:
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TForm1 = class(TForm)
Edit1: TEdit;
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
a:integer;
implementation
procedure test; external 'lib.dll' name 'test';
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
test;
Edit1.Text:=Inttostr(a);
end;
end.
和DLL文件:
library lib;
uses
Winapi.Windows, System.SysUtils;
var
a:integer;
procedure test;
begin
a:=6;
end;
exports
test;
{$R *.res}
begin
end.
问题是,Edit1.Text仍为0.你能帮助我吗?
答案 0 :(得分:1)
您有两个不同的变量,一个在DLL中,另一个在可执行文件中。他们都被命名为a
是偶然的。设置一个对另一个没有影响。
使DLL导出一个返回值的函数:
function GetValue: Integer; stdcall;
begin
Result := 6;
end;
像这样导入:
function GetValue: Integer; stdcall; external dllname;
并称之为:
Edit1.Text := IntToStr(GetValue);
毫无疑问,真正的代码所做的不仅仅是返回值6
,但这没有问题。你可以退回任何你喜欢的东西。它们的关键点是使用函数返回值将值从DLL传递给主机。
答案 1 :(得分:0)
效果很好:
在MainUnit中
implementation
procedure Test(Edit1: TEdit); stdcall; external 'dll_proj.dll';
在DLL中
exports Test;
Procedure Test(Object1: TEdit); stdcall;
var i:integer;
begin
for i:= 0 to 100 do
begin
Object1.Text:= IntToStr(i);
Application.Processmessages();
Sleep(100);
end;
end;
答案 2 :(得分:-2)
在您的原始代码的基础上添加更多按钮,这里演示了如何使用过程(或者您喜欢的功能)并让它们与 DLL < /强>
请注意,除非您希望更改函数的名称或使用重载,否则不需要name
选项 - 所以我已将其评论出来。
implementation
procedure test(var a : integer); external 'lib.dll' {name 'test'};
procedure test2(ptr_a : pinteger); external 'lib.dll';
procedure test3(ptr_a : pinteger); external 'lib.dll';
procedure test4(ptr_a : pinteger = nil); external 'lib.dll';
{$R *.dfm}
procedure TForm14.Button1Click(Sender: TObject);
begin
test(a);
Edit1.Text:=Inttostr(a);
end;
procedure TForm14.Button2Click(Sender: TObject);
begin
test2(@a);
Edit1.Text:=Inttostr(a);
end;
procedure TForm14.Button3Click(Sender: TObject);
begin
test3(@a);
Edit1.Text:=Inttostr(a);
end;
procedure TForm14.Button4Click(Sender: TObject);
begin
test4(@a);
test4;
Edit1.Text:=Inttostr(a);
end;
end.
......和图书馆的身体......
var
local_a:integer;
local_Ptr_a:pinteger;
procedure test(var a : integer);
begin
a:=6;
end;
procedure test2(ptr_a : pinteger);
begin
inc(ptr_a^);
end;
procedure test3(ptr_a : pinteger);
begin
inc(local_a);
ptr_a^:=local_a;
end;
procedure test4(ptr_a : pinteger = nil);
begin
if ptr_a = nil then
inc(local_ptr_a^)
else
local_ptr_a := ptr_a;
end;
exports test;
exports test2;
exports test3;
exports test4;
{$R *.res}
begin
local_a := 4;
end.
所以 - 稍微解释一下。
首先测试:使用var-parameter从过程返回一个值。没问题。
第二次测试:将接收变量的地址作为指针传递。我在这里添加了一点卷曲 - 增加娱乐价值,......值。
第三项测试:显示如何使用 DLL 拥有的本地值。 local 值由最后4
的赋值初始化。该过程本身使用与第二个测试相同的机制将DLL的局部变量中的值返回到主例程的变量。
注意test3
分配给程序的变量(1 +存储在DLL内存中的值),因此按下button3实际上会改变a
;所以按下按钮1-2-2-3-2将使用3中的值作为最后一次更改,而不是前一个值来自2。
最终测试:我们可以更聪明一点。它使用可选参数机制来改变详细操作。
首先,使用参数执行过程,作为的地址(或指向的指针)相应类型的变量。该过程将该地址存储在DLL的内存区域中。
接下来,您可以使用 no 参数执行该过程,它将递增存储指针所指向的整数。纯粹为了方便起见,我已经在每个按钮上建立了变量的地址,但是一旦存储了地址,无论该地址是在几微秒前还是在一周内设置,test4;
都会增加该地址的整数值 - 无论它是什么。使用test4(@b);
设置地址,然后test4;
将递增b
- 使用参数执行过程时最后指向的整数。
执行test4;
而没有在某个时间之前执行test4(@something)
或某些现在超出范围(可能是程序中的局部变量)非常可能会导致访问冲突。