delphi - 遇到大问题 : TDictionary and dll in Delphi 2010!

标签 delphi delphi-2010

当我试图从动态加载的 dll 访问主机程序中的 TDictionary 变量时,我遇到了一个非常严重的问题。这是完整的代码,任何人都可以提供一些帮助吗?谢谢!

===========主程序项目源码===================

program main;

uses
  ShareMem,
  Forms,
  uMain in 'uMain.pas' {Form1},
  uCommon in 'uCommon.pas';

{$R *.res}

begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.

==============单位uMain================
unit uMain;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, uCommon;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;


var
  Form1: TForm1;


implementation

{$R *.dfm}


type
  Tfoo = function(ADic: TMyDic): string; stdcall;

procedure TForm1.Button1Click(Sender: TObject);
var
  Dic: TMyDic;
  HLib: THandle;
  foo: Tfoo;
begin
  Dic := TMyDic.Create;
  try
    Dic.Add(1, 'World!');
    Dic.Add(2, 'Hello, ');

    HLib := LoadLibrary('Mydll.dll');
    try
      @foo := GetProcAddress(HLib, 'foo');
      ShowMessage(foo(Dic));
    finally
      FreeLibrary(HLib);
    end;
  finally
    Dic.Free;
  end;
end;

end.

=================dll项目源码=====================
library MyDll;

uses
  ShareMem,
  SysUtils,
  Classes,
  uCommon in 'uCommon.pas';

function foo(ADic: TMyDic):string; stdcall;
var
  I: Integer;
  S: string;
begin
  for I in ADic.Keys do
  begin
    S := S + ADic[I];
  end;
  Result := s;
end;


exports
  foo;

end.

================单位uCommon==============
unit uCommon;

interface
uses
  SysUtils, Generics.Collections;

type
  TMyDic = TDictionary<Integer, string>;



implementation

end.

最佳答案

你有异常(exception)吗?也许访问冲突或无效的指针操作?

如果 DLL 有自己的内存管理器,则不能在 Delphi 和 DLL 之间共享字符串和对象。由于您使用的是 Delphi 2010,因此您应该默认安装 FastMM。在 中添加“SimpleShareMem”作为第一件事使用 列出DLL和EXE,看看是否不能解决问题?

编辑:针对来自海报的其他信息:

卸载 DLL 后调用 dic.free。即使您共享内存管理器,也会给您带来访问冲突。这就是为什么。

免费调用TObject.Destroy,这是一个虚方法。编译器生成代码以在对象的虚拟方法表中查找它。但是 VMT 存储在特定于模块的静态内存中,而不是存储在内存管理器分配的共享内存中。您卸载了 DLL 并从对象中的 VMT 指针下方拉出地毯,因此当它尝试调用虚拟方法时,您会遇到访问冲突。

您可以通过确保在卸载 DLL 之前调用 Free 来解决此问题。或者,您可以使用运行时包而不是 DLL,通过将对象的 VMT 放入外部包中来解决此问题,该包在您完成之前不会被卸载。

关于delphi - 遇到大问题 : TDictionary and dll in Delphi 2010!,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3269613/

相关文章:

Delphi 2010 应用程序加载 Delphi 7 DLL

delphi - 在 Delphi 中,在 Excel Interop Worksheets 集合上使用 for 循环时,如何处理 "no GetEnumerator present"错误?

c++ - 如何在函数返回之前将新大小的数组从 C++ DLL 发送到 Delphi

delphi - 调整表单大小并保持纵横比

Delphi 2010 Action 管理器和主菜单栏

delphi - 具有事件处理程序的动态对象-Delphi

Delphi 64 位 Indy OpenSSL 库

德尔福。如何监控 IE 正在下载的 URL?

delphi - 无法使用 UTF-8 编码

delphi - 使用 TTime 作为 TDictionary 的键