Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi-从DLL修改变量_Delphi_Delphi Xe - Fatal编程技术网

Delphi-从DLL修改变量

Delphi-从DLL修改变量,delphi,delphi-xe,Delphi,Delphi Xe,我想制作一个简单的程序,将Edit1.Text设置为“6”(例如,但使用DLL-这很重要)。代码如下: 单位: 和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。你能帮我吗?你有两个不同的变量,一个在DLL中,一个

我想制作一个简单的程序,将Edit1.Text设置为“6”(例如,但使用DLL-这很重要)。代码如下: 单位:

和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。你能帮我吗?

你有两个不同的变量,一个在DLL中,一个在可执行文件中。它们都被命名为
a
,这是偶然的。设置一个对另一个没有影响

使DLL导出为返回以下值的函数:

function GetValue: Integer; stdcall;
begin
  Result := 6;
end;
按如下方式导入:

function GetValue: Integer; stdcall; external dllname;
Edit1.Text := IntToStr(GetValue);
这样称呼它:

function GetValue: Integer; stdcall; external dllname;
Edit1.Text := IntToStr(GetValue);

毫无疑问,真正的代码将不仅仅返回值
6
,但这不是问题。你可以退回任何你喜欢的东西。它们的关键点是使用函数返回值将值从DLL传递给主机

在原始代码的基础上,再添加几个按钮,下面演示如何使用过程(或函数,如果您愿意),并让它们与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参数从过程返回值。没问题

第二个测试:将接收变量的地址作为指针传递。我在这里加了一点卷曲,增加了娱乐的价值,呃,价值

第三个测试:显示如何使用DLL所拥有的local值。通过在末尾指定
4
来初始化局部值。该过程本身使用与第二个测试相同的机制将值从DLL的局部变量返回到主例程的变量

请注意,
test3
分配给程序的变量(1+存储在DLL内存中的值),因此按下按钮3将实际更改
a
;因此,按下按钮1-2-2-3-2将使用最后一次更改的值3,而不是先前的值2

最后的测试:在这里我们可以更聪明一点。它使用可选参数机制来改变详细操作

首先,使用一个参数执行过程,该参数是相应类型变量的地址(或指向该变量的指针)。该过程将该地址存储在DLL的内存区域中

接下来,您可以使用no参数执行该过程,它将递增存储指针指向的整数。纯粹为了方便起见,我在每次按下按钮时都会建立变量的地址,但一旦存储了地址,不管该地址是在几微秒前还是一周前设置的,
test4
将递增该地址处的整数值-无论它是什么。使用
test4(@b)设置地址然后
test4
将递增
b
——以在使用参数执行过程时最后指向的整数为准

执行
test4如果之前某个时候没有执行
测试4(@something)
,或者某个内容现在超出范围(比如过程中的局部变量),很可能会导致访问冲突。

效果良好:

在主机中

 implementation

  procedure Test(Edit1: TEdit); stdcall; external 'dll_proj.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;

如果需要在.exe和.dll之间共享变量,标准解决方案是使用内存映射文件。@user24我不这么认为。映射用于跨进程内存共享。这是in-proc。如果启动两个.exe副本并加载相同的.dll,则会跨进程运行。但我相信你不会同意:)@user24不。这是两个过程。但是我没有看到问题中的交叉过程。投票被否决,因为提议的解决方案类似于C,有点危险。OP:IOW,因为DLL通常是用C编写的,所以添加
cdecl是常规做法到程序头
程序测试(变量a:整数);cdecl;[外部文件名]
告诉Delphi应该使用C调用约定,而不是Delphi的。Delphi很高兴提供可执行文件的约定与DLL的约定相匹配,但很少有聪明的C程序员能够接受这个概念。因为我从来没有在愤怒中用C写过(只是作为一个学术练习),并且在二十年中几乎完全使用Delphi,所以在我自己的代码中,它是第二天性和自动的。