Decided to migrate from Delphi 2007 to Delphi 11 Alexandria. I had DLLs made with component creation from them. In the program, I dynamically load the DLL, a component is created in the DLL. Code that worked without issue on Delphi 2007 does not work on Delphi 11 Alexandria. Errors are constantly different, if I solve one error, another error appears. I can't find a solution. Please tell me how to create a component from a DLL.
My old code:
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.
Load DLL:
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;
I tried to create an ordinary Memo from a DLL. Another error, but it doesn't work either.
I need to understand how to create a SynPasSyn1 component from a DLL and connect it to SynMemo. Or at least using the example of any other component, I can figure it out myself further.
Here is an example of creating a Memo. Why does it give an error " cannot assign a TFont to a TFont" and how to solve it?
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.
How to create a component from a DLL?
2条答案
按热度按时间hfyxw5xn1#
错误消息“cannot assign TFont to a TFont”表示存在RTTI不匹配,因为
TFont
类DLL内部编译的类(和其他类)与TFont
类不同(和其他)在主机应用程序内编译。因此,当VCL在内部尝试将Assign()
对象从DLL转换为主机应用程序中的TFont
对象时(反之亦然),它无法验证它们是否是相同类类型的示例,因此它会失败,并出现上面的错误。当使用跨DLL边界的组件时,宿主应用程序和DLL * 必须 * 使用相同的 Delphi 版本编译,并且 * 必须 * 都启用Runtime Packages编译,因此它们可以共享RTL/VCL框架的 * 单个示例 * 以及内存中各自的所有RTTI。
否则,你不应该用一个普通的DLL来做这类工作,你应该用一个BPL Package来做(因此将
LoadLibrary()
替换为LoadPackage()
)。BPL包是一种特殊类型的DLL,内置了对RTL/VCL框架的支持。它旨在为您解决这类问题,而您必须在普通DLL中手动管理所有内容。阅读 Delphi 的文档了解更多细节:Working with Packages and Components Index
事实上,你的方法在 Delphi 2007中“工作”了 * 纯粹是运气 *。我所描述的是Delphi在所有版本中的操作方式。
顺便说一句:
在您的“旧”代码中,您的
TDLLComponent
类型被声明为错误。它应该是:a14dhokn2#
@RemyLebeau加载后,在Synmemo上高亮显示BPL代码。如果我只是开始在Synmemo中编写一些东西,那么一切都很好。但是如果我直接从 Delphi 插入这些代码到Synmemo中,那么立刻就会出现很多“访问冲突”错误。这不是关于组件的,因为如果我创建一个新项目,将Synmemo和SynPasSyn放在表单上,那么一切都很好。我想错了什么,我得到了一个“访问冲突”错误?
BPL:
Unit1.pas:
主机程序: