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

相关文章

Python结合PyWebView库打造跨平台桌面应用

《Python结合PyWebView库打造跨平台桌面应用》随着Web技术的发展,将HTML/CSS/JavaScript与Python结合构建桌面应用成为可能,本文将系统讲解如何使用PyWebView... 目录一、技术原理与优势分析1.1 架构原理1.2 核心优势二、开发环境搭建2.1 安装依赖2.2 验

Java字符串操作技巧之语法、示例与应用场景分析

《Java字符串操作技巧之语法、示例与应用场景分析》在Java算法题和日常开发中,字符串处理是必备的核心技能,本文全面梳理Java中字符串的常用操作语法,结合代码示例、应用场景和避坑指南,可快速掌握字... 目录引言1. 基础操作1.1 创建字符串1.2 获取长度1.3 访问字符2. 字符串处理2.1 子字

SpringShell命令行之交互式Shell应用开发方式

《SpringShell命令行之交互式Shell应用开发方式》本文将深入探讨SpringShell的核心特性、实现方式及应用场景,帮助开发者掌握这一强大工具,具有很好的参考价值,希望对大家有所帮助,如... 目录引言一、Spring Shell概述二、创建命令类三、命令参数处理四、命令分组与帮助系统五、自定

SpringBoot应用中出现的Full GC问题的场景与解决

《SpringBoot应用中出现的FullGC问题的场景与解决》这篇文章主要为大家详细介绍了SpringBoot应用中出现的FullGC问题的场景与解决方法,文中的示例代码讲解详细,感兴趣的小伙伴可... 目录Full GC的原理与触发条件原理触发条件对Spring Boot应用的影响示例代码优化建议结论F

MySQL 分区与分库分表策略应用小结

《MySQL分区与分库分表策略应用小结》在大数据量、复杂查询和高并发的应用场景下,单一数据库往往难以满足性能和扩展性的要求,本文将详细介绍这两种策略的基本概念、实现方法及优缺点,并通过实际案例展示如... 目录mysql 分区与分库分表策略1. 数据库水平拆分的背景2. MySQL 分区策略2.1 分区概念

Spring Shell 命令行实现交互式Shell应用开发

《SpringShell命令行实现交互式Shell应用开发》本文主要介绍了SpringShell命令行实现交互式Shell应用开发,能够帮助开发者快速构建功能丰富的命令行应用程序,具有一定的参考价... 目录引言一、Spring Shell概述二、创建命令类三、命令参数处理四、命令分组与帮助系统五、自定义S

C语言函数递归实际应用举例详解

《C语言函数递归实际应用举例详解》程序调用自身的编程技巧称为递归,递归做为一种算法在程序设计语言中广泛应用,:本文主要介绍C语言函数递归实际应用举例的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录前言一、递归的概念与思想二、递归的限制条件 三、递归的实际应用举例(一)求 n 的阶乘(二)顺序打印

Python中随机休眠技术原理与应用详解

《Python中随机休眠技术原理与应用详解》在编程中,让程序暂停执行特定时间是常见需求,当需要引入不确定性时,随机休眠就成为关键技巧,下面我们就来看看Python中随机休眠技术的具体实现与应用吧... 目录引言一、实现原理与基础方法1.1 核心函数解析1.2 基础实现模板1.3 整数版实现二、典型应用场景2

Python Dash框架在数据可视化仪表板中的应用与实践记录

《PythonDash框架在数据可视化仪表板中的应用与实践记录》Python的PlotlyDash库提供了一种简便且强大的方式来构建和展示互动式数据仪表板,本篇文章将深入探讨如何使用Dash设计一... 目录python Dash框架在数据可视化仪表板中的应用与实践1. 什么是Plotly Dash?1.1

Android Kotlin 高阶函数详解及其在协程中的应用小结

《AndroidKotlin高阶函数详解及其在协程中的应用小结》高阶函数是Kotlin中的一个重要特性,它能够将函数作为一等公民(First-ClassCitizen),使得代码更加简洁、灵活和可... 目录1. 引言2. 什么是高阶函数?3. 高阶函数的基础用法3.1 传递函数作为参数3.2 Lambda