【问题标题】:Accessing the content of TClientDataset loaded within a DLL in a Delphi Application访问在 Delphi 应用程序的 DLL 中加载的 TClientDataset 的内容
【发布时间】:2014-05-13 07:01:06
【问题描述】:

我的 DLL 具有要在 TClientDataSet 上执行的功能,例如要加载的设置文件以及文件的加载和保存。

unit dll_dmunit;

interface

uses
  System.SysUtils, System.Classes, Data.DB, Datasnap.DBClient, Vcl.Dialogs,Vcl.DBGrids;

type
  TStudentModule = class(TDataModule)
    StudentSet: TClientDataSet;
    StudentSource: TDataSource;
    StudentSetNAME: TStringField;
    StudentSetID: TIntegerField;
    StudentSetAGE: TIntegerField;
    StudentSetSLNo: TAutoIncField;
    dlgOpen: TOpenDialog;
    dlgSave: TSaveDialog;
    private
    { Private declarations }
  public
  end;

  function loadfile:tdbgrid;stdcall;
  procedure setfile(fname:string);stdcall;
  procedure savefile;stdcall;

var
  StudentModule: TStudentModule;
  filename:string;
  grid:TDBgrid;

const
  path:string='C:\Users\GlobalLogic\Documents\RAD Studio\Projects\Student\test.cds';

implementation

{%CLASSGROUP 'Vcl.Controls.TControl'}

{$R *.dfm}

  procedure setfile(f_name: string);stdcall;
  begin
    filename:=f_name;
  end;

  function loadfile:tdbgrid;stdcall;
  var
    _xmldata:string;
  begin
    StudentModule := TStudentModule.Create(nil);
    grid:=TDBGrid.Create(nil);
    result:=grid;
  try
    filename:='C:\Users\GlobalLogic\Documents\RAD Studio\Projects\Student\test.cds';
    StudentModule.StudentSet.LoadFromFile(filename);
    grid.DataSource:=StudentModule.StudentSource;
    _xmldata :=StudentModule.StudentSet.XMLData;
    result:=grid;
  finally
    StudentModule.Free;
  end;
    showmessage('End of the function');
  end;

  procedure  savefile;stdcall;
  begin
    StudentModule.StudentSet.SaveToFile(filename);
  end;
end.

我能够执行 loadfile 方法,但现在我需要将 TClientDataSet 的内容导出到 Delphi 应用程序。为此,我试图在 TDbgrid 中获取内容,然后将此对象返回到应用程序层,但我无法这样做。 然后我尝试读取 XML 格式,但不明白如何传递和解码 XML 格式。我需要将加载的数据集的内容移动到我想要显示数据的应用程序中。 请帮助我这样做。 谢谢你

【问题讨论】:

  • 您不能跨 DLL 边界传递 Delphi 对象。通过跨 DLL 边界使用字符串,您已经弄错了。您似乎正在寻找的是运行时包。如果您放弃单独的模块并将所有代码编译到可执行文件中,那会让您的生活变得更轻松。
  • @DavidHeffernan-我是这种语言的新手,所以我无法理解您的回复,您能否帮我提供一些代码或链接,让我更好地理解您所谈论的概念。
  • 在我知道您的目标和要求之前,我真的不想详细说明。
  • 有很多方法可以解决这个问题,但没有一种方法涉及跨 DLL 边界传递对象。您为什么决定使用 DLL?您是否打算在多个不同的可执行文件之间共享代码?为什么不将所有代码编译成一个可执行文件?
  • @Akash_Kumar:FWIW,您可以将整个 TClientDataSet 的数据(我的意思是它的数据属性,而不仅仅是它的“数据”)作为 OleVariant 跨 DLL 边界传递,并将其分配给另一侧的另一个 TClientDataSet边界。不过,您的导师可能会认为这是作弊 ;)

标签: delphi dll tclientdataset


【解决方案1】:

下面是一个简单的实现,它应该做你想做的事,而不必从你的 dll 中导出对象,这往往有点不合时宜。相反,只需导出包含您的数据的 XML 字符串。

重点是导出函数的签名(在本例中为function ExportXML:pwideChar;)和dllexport 部分。 确保将您的 XML 数据导出为 pwidechar

var Xmldata:widestring;
...
 function loadfile...
...
 Xmldata :=StudentModule.StudentSet.XMLData;

 function ExportXML:pwideChar;stdcall;
 begin
    result:= pwideChar( Xmldata);
 end;

exports
  ExportXML name 'ExportXML';

在您的应用程序中,只需将 DLL 调用ExportXML 的结果加载到TClientDataSet 实例中并将其插入您的控件。

有关使用 dll 的exports部分的更多方法,请参阅Using Export Clause in Libraries,这似乎是您所缺少的。

顺便说一句,如果您要从 Delphi 转到 Delphi,则不需要 stdcall 指令。见:

If you want your library to be available to applications written in other languages, 在 export 的声明中指定 stdcall 是最安全的 职能。其他语言可能不支持Delphi的默认寄存器 调用约定。

【讨论】:

  • 相比使用全局变量,返回WideString 更容易。由于ABI differences between different compilers,最好将其作为输出参数。我会这样声明函数:procedure ExportXML(const Intput: WideString; out Output: WideString); stdcall;
  • @DavidHeffernan - 同意。我不想卷入这一切。我只是在上面扔了一些或多或少适合问题中使用的代码的东西,以给出核心答案。重构等 - 那是另一回事。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-04-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-10
  • 1970-01-01
相关资源
最近更新 更多