从 DLL 创建组件,运行时

问题描述 投票:0回答:1

决定从 Delphi 2007 迁移到 Delphi 11 Alexandria。我用它们创建的组件制作了 DLL。在程序中,我动态加载了DLL,在DLL中创建了一个组件。在 Delphi 2007 上正常运行的代码不适用于 Delphi 11 Alexandria。错误总是不同的,如果我解决了一个错误,就会出现另一个错误。我找不到解决办法。请告诉我如何从 DLL 创建组件。

我的旧代码:

动态链接库:

library PascalHighlighter;

uses
  Forms,
  SynEditHighlighter, SynHighlighterPas, SynMemo;

{$R *.res}

var Component:TSynPasSyn;

type TSynPasSynClass = class of TSynPasSyn;

procedure PascalHighlighter_Create(Form:TForm; ComponentNum:Word);
begin
if Component=nil then begin
 Component := TSynPasSynClass.Create(Form);
 Component.Name:='SynPasSyn1';
end;
TSynmemo(Form.Components[ComponentNum]).Highlighter:=Component;
Component.CommentAttri.Foreground:=$00007F00;
Component.KeyAttri.Foreground:=$00A40000;
Component.StringAttri.Foreground:=$00FE0000;
end;

exports PascalHighlighter_Create;


begin
end.

加载动态链接库:

type

TDLLComponent = function(Form:TForm; ComponentNum: Word): Word;

var

PascalHighlighter_Create: TDLLComponent;
dll_PascalHighlighter: Thandle;

procedure TForm1.ButtinClick(Sender: TObject);
begin
if Fileexists(dirplugins+'PascalHighlighter.dll') then begin
 dll_PascalHighlighter:= LoadLibrary(PChar(dirplugins+'PascalHighlighter.dll'));
 @PascalHighlighter_Create:= GetProcAddress(dll_PascalHighlighter, 'PascalHighlighter_Create');
end;
if Assigned(PascalHighlighter_Create) then begin
 PascalHighlighter_Create(Form1,(Form1.Findcomponent('Synmemo1') as TSynmemo).ComponentIndex);
end;

end;

我试图从 DLL 创建一个普通的备忘录。另一个错误,但它也不起作用。

我需要了解如何从 DLL 创建 SynPasSyn1 组件并将其连接到 SynMemo。或者至少使用任何其他组件的示例,我可以自己进一步弄清楚。

这里是一个创建备忘录的例子。为什么会报错“cannot assign a TFont to a TFont”,如何解决?

library Mymemo;

uses
  Vcl.Forms, Vcl.StdCtrls;

{$R *.res}

var Component:TMemo;

procedure Mymemo_Create(Form:TForm); stdcall;
begin
 Component := TMemo.Create(Form);
 Component.Name:='Memo1';
with Component do begin
  Left := 100;
  Top := 100;
  Width := 400;
  Height := 300;
  Visible := True;
  Parent := Form; //Any container: form, panel, ...
end;

end;

exports Mymemo_Create;


begin
end.
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)
    Button1: TButton;
    Edit1: TEdit;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

type
 TDLLComponent = procedure(Form:TForm{; ComponentNum: Word}); stdcall;//: Word;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
 Mymemo_Create :TDLLComponent;
 dll_Mymemo :THandle;
 dirplugins :String;
begin
dirplugins:='E:\_Downloads\vk\Mymemo\';
 if Fileexists(dirplugins+'Mymemo.dll') then begin
   dll_Mymemo:= LoadLibrary(PChar(dirplugins+'Mymemo.dll'));
   if dll_Mymemo <> 0 Then begin
    edit1.Text:='load';
   end;
   //@
   Mymemo_Create:= GetProcAddress(dll_Mymemo, 'Mymemo_Create');
  if Assigned(Mymemo_Create) = True then begin
  edit1.Text:='load & create';
   Mymemo_Create(Form1);
  end;
 end;
end;

end.

如何从 DLL 创建组件?

delphi components runtime synedit
1个回答
0
投票

错误消息“cannot assign TFont to a TFont”意味着您有一个RTTI不匹配,因为在DLL中编译的

TFont
类(和其他类)与
TFont
类(和其他)在主机应用程序中编译。当 VCL 在内部尝试将 DLL 中的
Assign()
TFont
对象转换为主机应用程序中的
TFont
对象(反之亦然)时,它无法验证它们是同一类类型的实例,因此它因上述错误而失败。

当跨 DLL 边界使用组件时,主机应用程序和 DLL 必须 使用相同的 Delphi 版本进行编译,并且 必须 都在启用 运行时包 的情况下进行编译,这样它们就可以共享一个 单个实例 RTL/VCL 框架及其在内存中的所有 RTTI。

否则,您不应该开始使用普通 DLL 进行此类工作。你 应该BPL Package 代替(因此用

LoadLibrary()
替换
LoadPackage()
)。 BPL 包是一种特殊的 DLL,内置了对 RTL/VCL 框架的支持,可以解决这类问题。


旁注:

在您的“旧”代码中,您的

TDLLComponent
类型被声明为错误。应该是:

type
  //TDLLComponent = function(Form:TForm; ComponentNum: Word): Word;
  TDLLComponent = procedure(Form:TForm; ComponentNum: Word);
© www.soinside.com 2019 - 2024. All rights reserved.