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
尝试从dll加载过程时Delphi中出现错误_Delphi_Dll_Delphi Xe2 - Fatal编程技术网

尝试从dll加载过程时Delphi中出现错误

尝试从dll加载过程时Delphi中出现错误,delphi,dll,delphi-xe2,Delphi,Dll,Delphi Xe2,从dll加载过程时,无论是动态加载还是静态加载,我都遇到了问题。当我把程序从dll放到我的单元中时,一切都很好。当我尝试用dll做它时,它会给我 第一次机会例外价格为00526399美元。异常类别$C0000005,消息为“0x00526399处的访问冲突:读取地址0x00000390”。Process Project1.exe(21988) 单元1; 接口 使用 Winapi.Windows、Winapi.Messages、System.SysUtils、System.Variants、Sys

从dll加载过程时,无论是动态加载还是静态加载,我都遇到了问题。当我把程序从dll放到我的单元中时,一切都很好。当我尝试用dll做它时,它会给我

第一次机会例外价格为00526399美元。异常类别$C0000005,消息为“0x00526399处的访问冲突:读取地址0x00000390”。Process Project1.exe(21988)

单元1;
接口
使用
Winapi.Windows、Winapi.Messages、System.SysUtils、System.Variants、System.Classes、Vcl.Graphics、,
Vcl.控件、Vcl.窗体、Vcl.对话框、Vcl.StdCtrls、Vcl.ComCtrls、Unit2;
类型
TForm1=类(TForm)
ListView1:TListView;
按钮1:t按钮;
按钮2:t按钮;
编辑1:TEdit;
编辑2:TEdit;
编辑3:TEdit;
编辑4:TEdit;
编辑5:TEdit;
过程表单创建(发送方:ToObject);
过程FormClose(发送方:ToObject;var操作:TCloseAction);
程序刷新;
程序按钮1点击(发送方:ToObject);
私有的
{私有声明}
公众的
{公开声明}
结束;
变量
表1:TForm1;
实施
类型
plist=^元素;
元素=记录
艺术家、头衔、流派:弦乐[20];
年份、年级:整数;
wsk:plist;
结束;
数据库=元素的文件;
变量
数据库:数据库;
第一:plist;
处理程序:HModule;
{$R*.dfm}
过程TForm1.Refresh();
变量
当前:plist;
开始
ListView1.Clear;
电流:=第一;
而我做不到
开始
使用ListView1.Items.Add do
开始
标题:=当前^艺术家;
子项。添加(当前^标题);
添加子项(当前^体裁);
增加(IntToStr(本年度));
增加(IntToStr(当前等级));
结束;
当前:=当前^.wsk;
结束;
结束;
过程TForm1.FormClose(发送方:TObject;var操作:TCloseAction);
var保存:程序;
开始
处理程序:=LoadLibrary('lib.dll');
尝试
@Save:=GetProcAddress(处理程序,PChar(2));
如果@Save=nil,则引发异常.Create('Load nie dziala');
Save();
最后
免费图书馆(handler);
结束;
结束;
过程TForm1.FormCreate(发送方:TObject);
变量
加载:程序;
开始
处理程序:=LoadLibrary('lib.dll');
尝试
@Load:=GetProcAddress(处理程序,PChar(1));
如果@Load=nil,则引发异常。Create('Load nie dziala');
加载();
最后
免费图书馆(handler);
结束;
刷新();
结束;
程序TForm1.按钮1单击(发送方:TObject);
变量
el:元素;
新增:程序(el:要素);
开始
el.艺术家:=Edit1.Text;
el.title:=Edit2.Text;
el.类型:=Edit3.Text;
el.年份:=标准输入(编辑4.文本);
el.grade:=STROTINT(编辑5.Text);
处理程序:=LoadLibrary('lib.dll');
尝试
@Add:=GetProcAddress(处理程序,PChar(3));
如果@Add=nil,则引发异常.Create('Load nie dziala');
加(el);
最后
免费图书馆(handler);
刷新();
{Form2:=TForm2.Create(Form1);
表2.1;
Form2.Free;}
结束;
结束;
结束。
dll文件如下所示:

  library lib;

{ 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
  System.SysUtils,
  System.Classes;

{$R *.res}

type plist = ^element;
element = record
  artist,title,genre:string[20];
  year,grade:integer;
  wsk: plist;
end;
database = file of element;

var
first: plist;
base: database;

procedure add(el: element); stdcall;
var current,tmp: plist;
begin
New(current);
current^ := el;
current^.wsk := nil;
if first = nil then
begin
  first:=current;
end else
begin
  tmp:=first;
  while tmp^.wsk<>nil do
  begin
    tmp:=tmp^.wsk;
  end;
  tmp^.wsk:=current;
end;

end;

procedure load();stdcall;
var
  el: element;
  i: integer;
begin
  AssignFile(base, 'baza.dat');
  if not FileExists('baza.dat') then
  begin
    Rewrite(base);
  end else
  begin
    Reset(base);
    for i := 0 to FileSize(base)-1 do
    begin
        read(base, el);
        add(el);
    end;
  end;
  CloseFile(base);
end;

procedure save();stdcall;
var
current: plist;
el: element;
begin
  AssignFile(base, 'baza.dat');
  Rewrite(base);
  current:=first;
  while current<>nil do
  begin
    el:=current^;
    el.wsk:=nil;
    write(base, el);
    current:= current^.wsk;
  end;
end;

exports
add index 1,
load index 2,
save index 3;
begin
end.
lib库;
{有关DLL内存管理的重要注意事项:ShareMem必须是
库的USES子句中的第一个单元和项目的(选择
项目视图(源代码)如果DLL导出任何过程或
将字符串作为参数或函数结果传递的函数
应用于从DLL传递到DLL的所有字符串,即使是
嵌套在记录和类中。ShareMem是
BORLNDMM.DLL共享内存管理器,必须随
要避免使用BORLNDMM.DLL,请传递字符串信息
使用PChar或短字符串参数。}
使用
System.SysUtils,
系统、班级;
{$R*.res}
类型plist=^element;
元素=记录
艺术家、头衔、流派:弦乐[20];
年份、年级:整数;
wsk:plist;
结束;
数据库=元素的文件;
变量
第一:plist;
数据库:数据库;
程序添加(el:元素);stdcall;
无功电流,tmp:plist;
开始
新的(当前的);
当前^:=el;
当前^.wsk:=nil;
如果first=nil,则
开始
第一:=电流;
结束其他
开始
tmp:=第一;
而tmp^.wsknil
开始
tmp:=tmp^.wsk;
结束;
tmp^.wsk:=当前;
结束;
结束;
程序加载();stdcall;
变量
el:元素;
i:整数;
开始
AssignFile(基'baza.dat');
如果文件不存在('baza.dat'),则
开始
重写(基础);
结束其他
开始
复位(基本);
对于i:=0的文件大小(基本)-1 do
开始
读取(基准,el);
加(el);
结束;
结束;
关闭文件(基本);
结束;
程序保存();stdcall;
变量
当前:plist;
el:元素;
开始
AssignFile(基'baza.dat');
重写(基础);
电流:=第一;
而我做不到
开始
el:=当前^;
el.wsk:=零;
写入(基,el);
当前:=当前^.wsk;
结束;
结束;
出口
添加索引1,
负荷指数2,
保存索引3;
开始
结束。
它还向我显示了一个错误:

期望“;”但在第91行接收到和标识符“index”


但是导出是像web上的红色一样完成的。

明显的错误是:

  • 您没有执行太多的错误检查。您假定对
    LoadLibrary
    的调用总是成功的
  • 呼叫约定不匹配。在DLL中使用
    stdcall
    ,在可执行文件中使用
    register
  • 序号不匹配。在DLL中是添加(1)、加载(2)和保存(3)。在可执行文件中添加(3)、加载(1)和保存(2)
  • 每次从DLL调用函数时,都会加载和卸载DLL。这意味着每次卸载DLL时,DLL中保存您的状态的全局变量都会丢失
坦率地说,这段代码真是一团糟。我建议您执行以下操作:

  • 使用函数名而不是序号切换到加载时间链接。这意味着在可执行文件中使用
    external
    关键字。这将通过删除对
    LoadLibrary
    GetProcAddress
    等的所有调用来大大简化代码。如果需要运行时链接,您可以稍后使用
    delayed
    关键字添加它
  • 停止在DLL中使用全局状态,而是在模块之间来回传递信息。全部删除
      library lib;
    
    { 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
      System.SysUtils,
      System.Classes;
    
    {$R *.res}
    
    type plist = ^element;
    element = record
      artist,title,genre:string[20];
      year,grade:integer;
      wsk: plist;
    end;
    database = file of element;
    
    var
    first: plist;
    base: database;
    
    procedure add(el: element); stdcall;
    var current,tmp: plist;
    begin
    New(current);
    current^ := el;
    current^.wsk := nil;
    if first = nil then
    begin
      first:=current;
    end else
    begin
      tmp:=first;
      while tmp^.wsk<>nil do
      begin
        tmp:=tmp^.wsk;
      end;
      tmp^.wsk:=current;
    end;
    
    end;
    
    procedure load();stdcall;
    var
      el: element;
      i: integer;
    begin
      AssignFile(base, 'baza.dat');
      if not FileExists('baza.dat') then
      begin
        Rewrite(base);
      end else
      begin
        Reset(base);
        for i := 0 to FileSize(base)-1 do
        begin
            read(base, el);
            add(el);
        end;
      end;
      CloseFile(base);
    end;
    
    procedure save();stdcall;
    var
    current: plist;
    el: element;
    begin
      AssignFile(base, 'baza.dat');
      Rewrite(base);
      current:=first;
      while current<>nil do
      begin
        el:=current^;
        el.wsk:=nil;
        write(base, el);
        current:= current^.wsk;
      end;
    end;
    
    exports
    add index 1,
    load index 2,
    save index 3;
    begin
    end.