delphi的BPL应用

2023-11-09 02:10
文章标签 应用 delphi bpl

本文主要是介绍delphi的BPL应用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

最近一直在测试BPL和DLL,总结一下这段时间的经验。
如果是模块化架构,就选择BPL,不要选择DLL,DLL可以对外做接口使用,不过Delphi接口我觉得DataSnap更方便点。为什么要用BPL呢,因为DLL是无法传递对象的,只能传递对象的内存地址过去。BPL就可以实现对象的传递。
使用BPL的注意事项,首先一定要注意Debug 和Release 两种编译是有很大区别的。直接Release编译最好,主程序也要用Release编译调用,如果编译类型不同,会有异常提示。BPL里面各个Form和Unit之间的调用,需要注意的如果用到了Form的控件,记得一定要把Form对象传过去。这样获取才不会出问题。BPL调用BPL的时候,也要把Form传过去,传回来的时候再转换回来。下面说下调用案例。
我是一个主程序,两个BPL
主程序调用的代码

procedure TFMenuItem.Label1DblClick(Sender: TObject);
varBPLHandle: HMODULE;frm: TCustomForm;AClass : TPersistentClass;SetUser:procedure(sform:TForm;User:String;IP:String;Port:Integer);newPage:TAdvTabSheet;Path:String;ClassName:String;SetName:String;
begin//BPL的目录和名称Path:='System/'+Copy(self.Caption,1,2)+'.bpl';//调用的Form的名称ClassName:='T'+self.Caption;//BPL里面的过程名称SetName:=self.Caption+'SetUser';//加载BPLBPLHandle := LoadPackage(Path);//加载后获取过程@SetUser := GetProcAddress(BPLHandle, Pchar(SetName));if BPLHandle > 0 thenbegin//获取FormAClass := FindClass(ClassName);if AClass<>nil thenbegin//新增一个Page页面newPage:=TAdvTabSheet.Create(FMyMain.AdvPageControl2);newPage.Caption:=Label1.Caption;newPage.Color:=clWhite;newPage.AdvPageControl:=FMyMain.AdvPageControl2;newPage.ShowClose:=True;FMyMain.AdvPageControl2.ActivePage:=newPage;//创建BPL的Form实例frm:=TComponentClass(AClass).Create(Application) as TCustomForm;if @SetUser<>nil then//执行BPL里面的过程SetUser(TForm(frm),'admin',FMyMain.DSRestConnection1.Host,FMyMain.DSRestConnection1.Port);//放入新建的Page里面frm.Parent:=newPage;//显示frm.Show;// frm.Free;endend
end;

第一个BPL的代码

unit User;interfaceusesWinapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,System.Classes, Vcl.Graphics,Vcl.Controls, Vcl.Forms, Vcl.Dialogs, DBGridEhGrouping, ToolCtrlsEh,DBGridEhToolCtrls, DynVarsEh, FireDAC.Stan.Intf, FireDAC.Stan.Option,FireDAC.Stan.Param, FireDAC.Stan.Error, FireDAC.DatS, FireDAC.Phys.Intf,FireDAC.DApt.Intf, Vcl.ComCtrls, Vcl.ToolWin, System.ImageList, Vcl.ImgList,Data.DB, FireDAC.Comp.DataSet, FireDAC.Comp.Client, EhLibVCL, GridsEh,DBAxisGridsEh, DBGridEh, AdvEdit, AdvEdBtn, Vcl.StdCtrls, Vcl.ExtCtrls,Datasnap.DSClientRest, FireDAC.Stan.StorageJSON,FireDAC.Stan.StorageXML, FireDAC.Stan.StorageBin,DataBase;type//定义回调过程MeADD=procedure(DepCode:String;DepName:String;MyForm:TForm);TF901 = class(TForm)Panel1: TPanel;Label1: TLabel;Label2: TLabel;Label3: TLabel;Label4: TLabel;Label5: TLabel;Label6: TLabel;Edit1: TEdit;Edit2: TEdit;Edit3: TEdit;Edit4: TEdit;Edit5: TEdit;Edit7: TEdit;Edit6: TAdvEditBtn;Panel2: TPanel;DBGridEh1: TDBGridEh;Panel3: TPanel;DataSource1: TDataSource;FDMemTable1: TFDMemTable;ImageList1: TImageList;ToolBar1: TToolBar;ToolButton1: TToolButton;ToolButton2: TToolButton;ToolButton3: TToolButton;ToolButton4: TToolButton;ToolButton10: TToolButton;ToolButton5: TToolButton;ToolButton6: TToolButton;ToolButton7: TToolButton;ToolButton8: TToolButton;procedure ToolButton1Click(Sender: TObject);procedure ToolButton2Click(Sender: TObject);procedure ToolButton3Click(Sender: TObject);procedure ToolButton4Click(Sender: TObject);procedure ToolButton10Click(Sender: TObject);procedure FormShow(Sender: TObject);procedure ToolButton8Click(Sender: TObject);procedure Edit6ClickBtn(Sender: TObject);private{ Private declarations }public{ Public declarations }varUserNo:String;MyDataBase:TDDataBase;end;//定义给主程序调用的过程procedure F901SetUser(sform:TForm;UserNo:String;IP:String;Port:Integer);//定义一个跟回调过程一样的过程,这个用于回调过程功能实现procedure SetDep(depcode:String;depname:String;MyForm:TForm);
varF901: TF901;implementation
Uses DataPost;
{$R *.dfm}//给主程序调用的过程
procedure F901SetUser(sform:TForm;UserNo:String;IP:String;Port:Integer);
beginTF901(sform).UserNo:=UserNo;TF901(sform).MyDataBase:=DataPost.ConnectData(IP,Port);
end;//一个跟回调过程一样的过程,这个用于回调过程功能实现
procedure SetDep(depcode:String;depname:String;MyForm:TForm);
beginTF901(MyForm).Edit7.Text:=depcode;TF901(MyForm).Edit6.Text:=depname;
end;//BPL里面调用另外一个BPL
procedure TF901.Edit6ClickBtn(Sender: TObject);
varBPLHandle: HMODULE;frm: TCustomForm;AClass : TPersistentClass;DepSetUser:procedure(sform:TForm;tForm:TForm;User:String;IP:String;Port:Integer);PMeADD:procedure(me:MeADD);
begin//加载BPLBPLHandle := LoadPackage('Share/DepBPL.bpl');//这里跟主程序调用的一样,调用另外一个BPL的过程@DepSetUser := GetProcAddress(BPLHandle, 'DepSetUser');//另外一个BPL回调本BPL的过程@PMeADD := GetProcAddress(BPLHandle, 'PMeADD');if BPLHandle > 0 thenbegin//获取FormAClass := FindClass('TFQueryDep');if AClass<>nil thenbegin//创建另外一个BPL的Form实例frm:=TComponentClass(AClass).Create(Application) as TCustomForm;if @DepSetUser<>nil then//调用里面的过程 DepSetUser(TForm(frm),self,'admin',MyDataBase.DSRestConnection1.Host,MyDataBase.DSRestConnection1.Port);if @PMeADD<>nil then//把实现回调功能的过程传过去PMeADD(SetDep);frm.ShowModal;frm.Free;endendend;procedure TF901.FormShow(Sender: TObject);
beginDataPost.ButtonPower(Self.Name,self.UserNo,self.ToolBar1,self.MyDataBase);DataPost.F901OpenData(self);
end;procedure TF901.ToolButton10Click(Sender: TObject);
beginDataPost.F901Cancel(self);
end;procedure TF901.ToolButton1Click(Sender: TObject);
beginDataPost.F901Add(self);
end;procedure TF901.ToolButton2Click(Sender: TObject);
beginDataPost.F901Update(self);
end;procedure TF901.ToolButton3Click(Sender: TObject);
beginDataPost.F901Delete(self);end;procedure TF901.ToolButton4Click(Sender: TObject);
beginDataPost.F901Save(self);
end;procedure TF901.ToolButton8Click(Sender: TObject);
beginDataPost.F901Cancel(self);
end;//这里是给主程序显示可调用的过程
exportsF901SetUser;//这里把Form给主程序定位Form使用
initializationRegisterClass(TF901);
finalizationUnRegisterClass(TF901);end.

第二个BPL代码

unit QueryDep;interfaceusesWinapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,Vcl.Controls, Vcl.Forms, Vcl.Dialogs, DBGridEhGrouping, ToolCtrlsEh,DBGridEhToolCtrls, DynVarsEh, EhLibVCL, GridsEh, DBAxisGridsEh, DBGridEh,FireDAC.Stan.Intf, FireDAC.Stan.Option, FireDAC.Stan.Param,FireDAC.Stan.Error, FireDAC.DatS, FireDAC.Phys.Intf, FireDAC.DApt.Intf,FireDAC.Stan.Async, FireDAC.DApt, Data.DB, FireDAC.Comp.DataSet,FireDAC.Comp.Client, Vcl.StdCtrls, Vcl.ExtCtrls, Vcl.Imaging.pngimage,Vcl.ShadowForms,Datasnap.DSClientRest,system.IniFiles,Data.FireDACJSONReflect,FireDAC.Stan.StorageXML, FireDAC.Stan.StorageJSON, FireDAC.Stan.StorageBin;type//定义回调过程MeADD=procedure(DepCode:String;DepName:String;MyForm:TForm);TFQueryDep = class(TShadowForm)DBGridEh1: TDBGridEh;DataSource1: TDataSource;Panel1: TPanel;Label4: TLabel;Image1: TImage;Panel3: TPanel;Panel4: TPanel;DSRestConnection1: TDSRestConnection;FDMemTable1: TFDMemTable;FDStanStorageBinLink1: TFDStanStorageBinLink;FDStanStorageJSONLink1: TFDStanStorageJSONLink;FDStanStorageXMLLink1: TFDStanStorageXMLLink;procedure FormClose(Sender: TObject; var Action: TCloseAction);procedure FormDestroy(Sender: TObject);procedure DBGridEh1DblClick(Sender: TObject);procedure Image1Click(Sender: TObject);procedure FormShow(Sender: TObject);private{ Private declarations }public{ Public declarations }varUserNo:String;//用于接收上一个BPL的Form,后面调用回调过程的时候会传回去Form:TForm;end;//顶一个回调过程功能实现,用于调用上一个BPL的回调过程接收procedure PMeADD(me:MeADD);//定义上一个BPL调用过程procedure DepSetUser(sform:TForm;UserNo:String;IP:String;Port:Integer);varFQueryDep: TFQueryDep;FMeADD:MeADD;implementation
Uses Server;{$R *.dfm}
//上一个BPL调用过程的功能实现
procedure DepSetUser(sform:TForm;UserNo:String;IP:String;Port:Integer);
beginTFQueryDep(sform).UserNo:=UserNo;TFQueryDep(sform).Form:=sform;TFQueryDep(sform).DSRestConnection1.Host:=IP;TFQueryDep(sform).DSRestConnection1.Port:=Port;
end;
//用于接收传过来的过程
procedure PMeADD(me:MeADD);
beginFMeADD:=ME;
end;procedure TFQueryDep.DBGridEh1DblClick(Sender: TObject);
begin
//调用回调过程,把值和Form传回去   FMeADD(DBGridEh1.DataSource.DataSet.FieldByName('cDepCode').AsString,DBGridEh1.DataSource.DataSet.FieldByName('cDepName').AsString,Form);close;
end;procedure TFQueryDep.FormClose(Sender: TObject; var Action: TCloseAction);
begin//  Action := caFree;
end;procedure TFQueryDep.FormDestroy(Sender: TObject);
beginFQueryDep := nil;
end;procedure TFQueryDep.FormShow(Sender: TObject);
varServer: TServerMethods1Client;DSlIST: TFDJSONDataSets;
beginServer := TServerMethods1Client.Create(DSRestConnection1);DSlIST := Server.ServerGetTable('select * from Department order by cDepCode', UserNo, 1);FDMemTable1.FieldDefs.Clear;FDMemTable1.Close;FDMemTable1.Data := TFDJSONDataSetsReader.GetListValue(DSlIST, 0).Data;FDMemTable1.Open;
end;procedure TFQueryDep.Image1Click(Sender: TObject);
beginclose;
end;//给另外一个BPL获取过程使用
exportsPMeADD,DepSetUser;//给另外一个BPL获取Form使用
initializationRegisterClass(TFQueryDep);
finalizationUnRegisterClass(TFQueryDep);end.

主要代码就这些
调用第一个BPL
在这里插入图片描述
通过第一个BPL调用第二个BPL

在这里插入图片描述

点击后,把第二个BPL的值,通过回调过程传递到一个BPL里面
在这里插入图片描述

这篇关于delphi的BPL应用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/373575

相关文章

PHP应用中处理限流和API节流的最佳实践

《PHP应用中处理限流和API节流的最佳实践》限流和API节流对于确保Web应用程序的可靠性、安全性和可扩展性至关重要,本文将详细介绍PHP应用中处理限流和API节流的最佳实践,下面就来和小编一起学习... 目录限流的重要性在 php 中实施限流的最佳实践使用集中式存储进行状态管理(如 Redis)采用滑动

深入浅出Spring中的@Autowired自动注入的工作原理及实践应用

《深入浅出Spring中的@Autowired自动注入的工作原理及实践应用》在Spring框架的学习旅程中,@Autowired无疑是一个高频出现却又让初学者头疼的注解,它看似简单,却蕴含着Sprin... 目录深入浅出Spring中的@Autowired:自动注入的奥秘什么是依赖注入?@Autowired

PostgreSQL简介及实战应用

《PostgreSQL简介及实战应用》PostgreSQL是一种功能强大的开源关系型数据库管理系统,以其稳定性、高性能、扩展性和复杂查询能力在众多项目中得到广泛应用,本文将从基础概念讲起,逐步深入到高... 目录前言1. PostgreSQL基础1.1 PostgreSQL简介1.2 基础语法1.3 数据库

Python中的filter() 函数的工作原理及应用技巧

《Python中的filter()函数的工作原理及应用技巧》Python的filter()函数用于筛选序列元素,返回迭代器,适合函数式编程,相比列表推导式,内存更优,尤其适用于大数据集,结合lamb... 目录前言一、基本概念基本语法二、使用方式1. 使用 lambda 函数2. 使用普通函数3. 使用 N

Python中yield的用法和实际应用示例

《Python中yield的用法和实际应用示例》在Python中,yield关键字主要用于生成器函数(generatorfunctions)中,其目的是使函数能够像迭代器一样工作,即可以被遍历,但不会... 目录python中yield的用法详解一、引言二、yield的基本用法1、yield与生成器2、yi

Python多线程应用中的卡死问题优化方案指南

《Python多线程应用中的卡死问题优化方案指南》在利用Python语言开发某查询软件时,遇到了点击搜索按钮后软件卡死的问题,本文将简单分析一下出现的原因以及对应的优化方案,希望对大家有所帮助... 目录问题描述优化方案1. 网络请求优化2. 多线程架构优化3. 全局异常处理4. 配置管理优化优化效果1.

从基础到高阶详解Python多态实战应用指南

《从基础到高阶详解Python多态实战应用指南》这篇文章主要从基础到高阶为大家详细介绍Python中多态的相关应用与技巧,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、多态的本质:python的“鸭子类型”哲学二、多态的三大实战场景场景1:数据处理管道——统一处理不同数据格式

Java Stream 的 Collectors.toMap高级应用与最佳实践

《JavaStream的Collectors.toMap高级应用与最佳实践》文章讲解JavaStreamAPI中Collectors.toMap的使用,涵盖基础语法、键冲突处理、自定义Map... 目录一、基础用法回顾二、处理键冲突三、自定义 Map 实现类型四、处理 null 值五、复杂值类型转换六、处理

分布式锁在Spring Boot应用中的实现过程

《分布式锁在SpringBoot应用中的实现过程》文章介绍在SpringBoot中通过自定义Lock注解、LockAspect切面和RedisLockUtils工具类实现分布式锁,确保多实例并发操作... 目录Lock注解LockASPect切面RedisLockUtils工具类总结在现代微服务架构中,分布

Python标准库之数据压缩和存档的应用详解

《Python标准库之数据压缩和存档的应用详解》在数据处理与存储领域,压缩和存档是提升效率的关键技术,Python标准库提供了一套完整的工具链,下面小编就来和大家简单介绍一下吧... 目录一、核心模块架构与设计哲学二、关键模块深度解析1.tarfile:专业级归档工具2.zipfile:跨平台归档首选3.