说三道四技术文摘-感悟人生的经典句子
说三道四 > 文档快照

Delphi 插件创建、调试与使用应用程序扩展

HTML文档下载 WORD文档下载 PDF文档下载
Delphi 插件创建、调试与使用应用程序扩展

有没有使用过Adobe Photoshop如果用过,你就会对插件的概念比较熟悉。对外行人来说,插件仅仅是从外部提供给应用程序的代码块而已(举个例子来说,在一个DLL中)。一个插件和一个普通DLL之间的差异在于插件具有扩展父应用程序功能的能力。例如,Photoshop本身并不具备进行大量的图像处理功能。插件的加入使其获得了产生诸如模糊、斑点,以及其他所有风格的奇怪效果,而其中任何一项功能都不是父应用程序自身所具有的。

对于图像处理程序来说这很不错,可是为什么要花偌大的力气去完成支持插件的商业应用程序呢?假设,我们举个例子,你的应用程序要产生一些报表。你的客户肯定会一直要求更新或者增加新的报表。你可以使用一个诸如Report Smith的外部报表生成器,这是个不怎么样的解决方案,需要发布附加的文件,要对用户进行额外的培训,等等。你也可以使用QuickReport,不过这会使你身处版本控制的噩梦之中——如果每改变一次字体你就要Rebuild你的应用程序的话。

然而,只要你把报表做到插件中,你就可以使用它。需要一个新的报表吗?没问题,只要安装一个DLL,下次应用程序启动时就会看见它了。另外一个例子是处理来自外部设备(比如条形码扫描器)的数据的应用程序,为了给用户更多的选择,你不得不支持半打的各种设备。通过将每种设备接口处理例程写成插件,不用对父应用程序作任何变动就可以获得最大程度的可伸缩性。

入门

在开始写代码之前最重要的事情就是搞清楚你的应用程序到底需要扩展哪些功能。这是因为插件是通过一个特定的接口与父应用程序交互的,而这个接口将根据你的需要来定义。在本文中,我们将建立3个插件,以便展示插件与父应用程序相交互的几种方式。

我们将把插件制作成DLL。不过,在做这项工作之前,我们得先制作一个外壳程序来载入和测试它们。图1显示的是加载了第一个插件以后的测试程序。第一个插件没有完成什么大不了的功能,实际上,它所做的只是返回一个描述自己的字符串。不过,它证明了很重要的一点——不管有没有插件应用程序都可以正常运行。如果没有插件,它就不会出现在已安装的插件列表中,但是应用程序仍然可以正常的行使功能。

我们的插件外壳程序与普通应用程序之间的唯一不同就在于工程源文件中出现在uses子句中的Sharemem单元和加载插件文件的代码。任何在自身与子DLL之间传递字符串参数的应用程序都需要Sharemem单元,它是DelphiMM.dll(Delphi提供该文件)的接口。要测试这个外壳,需要将DelphiMM.dll文件从Delphi\Bin目录复制到path环境变量所包含的路径或者应用程序所在目录中。发布最终版本时也需要同时分发该文件。

插件通过LoadPlugins过程载入到这个测试外壳中,这个过程在主窗口的FormCreate事件中调用,见图2。该过程使用FindFirst和FindNext函数在应用程序所在目录中查找插件文件。找到一个文件以后,就使用图3所示的LoadPlugins过程将其载入。

{ 在应用程序目录下查找插件文件 }

procedure TfrmMain.LoadPlugins;

var

sr: TSearchRec;

path: string;

Found: Integer;

begin

path := ExtractFilePath(Application.Exename);

try

Found := FindFirst(path + cPLUGIN_MASK

0

sr);

while Found = 0 do begin

LoadPlugin(sr);

Found := FindNext(sr);

end;

finally

FindClose(sr);

end;

end;

{ 加载指定的插件 DLL. }

procedure TfrmMain.LoadPlugin(sr: TSearchRec);

var

Description: string;

LibHandle: Integer;

DescribeProc: TPluginDescribe;

begin

LibHandle := LoadLibrary(Pchar(sr.Name));

if LibHandle <> 0 then

begin

DescribeProc := GetProcAddress(LibHandle

cPLUGIN_DESCRIBE);

if Assigned(DescribeProc) then

begin

DescribeProc(Description);

memPlugins.Lines.Add(Description);

end

else

begin

MessageDlg(’File "’ + sr.Name + ’" is not a valid plug-in.’

mtInformation

[mbOK]

0);

end;

end

else

MessageDlg(’An error occurred loading the plug-in "’ +

sr.Name + ’".’

mtError

[mbOK]

0);

end;

LoadPlugin方法展示了插件机制的核心。首先,插件被写成DLL。其次,通过LoadLibrary API它被动态的加载。一旦DLL被加载,我们就需要一个访问它所包含的过程和函数的途径。API调用GetProcAddress提供这种机制,它返回一个指向所需例程的指针。在我们这个简单的演示中,插件仅仅包含一个名为DescribePlugin的过程,由常数cPLUGIN_DESCRIBE指定(过程名的大小写非常重要,传递到GetProcAddress的名称必须与包含在DLL中的例程名称完全一致)。如果在DLL中没有找到请求的例程,GetProcAddree将返回nil,这样就允许使用Assigned函数测定返回值。

为了以一种易用的方式存储指向一个函数的指针,有必要为用到的变量创建一个特定的类型。注意,GetProcAddress的返回值被存储在一个变量中,DescribeProc,属于TpluginDescribe类型。下面是它的声明:

type

TPluginDescribe = procedure(var Desc: string); stdcall;

由于过程存在于DLL内部,它通过标准调用转换编译所有导出例程,因此需要使用stdcall指示字。这个过程使用一个var参数,当过程返回的时候它包含插件的描述。

要调用刚刚获得的过程,只需要使用保存地址的变量作为过程名,后面跟上任何参数。就我们的例子而言,声明:

DescribeProc(Description)

将会调用在插件中获得的描述过程,并且用描述插件功能的字符串填充Description变量。

构造插件

我们已经创建好了父应用程序,现在该轮到创建我们希望加载的插件了。插件文件是一个标准的Delphi DLL,所以我们从Delphi IDE中创建一个新DLL工程,保存它。由于导出的插件函数将用到字符串参数,所以要在工程的uses子句中把Sharemen单元放在最前面。图4列出的就是我们这个简单插件的工程源文件。

uses

Sharemem

SysUtils

Classes

main in ’main.pas’;

{$E plg.}

exports

DescribePlugin;

begin

end.

虽然插件是一个DLL文件,但是没有必要一定要给它一个.DLL的扩展名。实际上,一个原因就足以让我们有理由改变扩展名:当父应用程序寻找要加载的文件时,新的扩展名可以作为特定的文件掩模。通过使用别的扩展名(我们的例子使用了*.plg),你可以在一定程度上确信应用程序只会载入相应的文件。编译指示字$X可以实现这个改变,也可以通过Project Options对话框的Application页来设置扩展名。

第一个例子插件的代码是很简单的。图5显示了包含在一个新单元中的代码。注意,DescribePlugin原型与外壳应用程序中的TpluginDescribe类型相一致,使用附加的export保留字指定该过程将被导出。被导出的过程名称也将会出现在主工程源代码的exports段中(在图4中列出)。

unit main;

interface

procedure DescribePlugin(var Desc: string);

export; stdcall;

implementation

procedure DescribePlugin(var Desc: string);

begin

Desc := ’Test plugin v1.00’;

end;

end.

在测试这个插件之前,要先把它复制到主应用程序的路径下。最简单的办法就是在主目录的子目录下创建插件,然后把输出路径设置为主路径(Project Options对话框的Directories/Conditionals也可以作这个设置)。

调试

现在介绍一下Delphi 3中一个较好的功能:从IDE中调试DLL的能力。在DLL工程中可以通过Run paramaters对话框指定某程序为宿主应用程序,这就是指向将调用DLL的应用程序的路径(在我们这个例子中,就是刚刚创建的测试外壳程序)。然后你就可以在DLL代码中设置断点并且按F9运行它——就像在一个普通应用程序中做的那样。Delphi会运行指定的宿主程序,并且,通过编译带有调试信息的DLL,把你指引到DLL代码内的断点处。

国外一学生发明新计算机系统,用微芯片代替硬盘 《近匠》第12期:Yeelink——智能硬件云服务 三星Galaxy S5:home键内置指纹识别传感器、5.25寸2K屏幕 Google发布Google Glass使用守则 三星将发布新款智能手表 搭载Tizen系统抛弃Android 从Camera360 V5版本发布,看现代相机应用趋势 索契冬奥会API:赛事的数据直播 为什么开源企业的开源大旗正在褪色 尘埃落定 腾讯确认投资大众点评,获20%股份 Unite China&#183;2014:上千Unity开发者狂欢、五大精品课程全面开启 下载4万首歌曲仅需几秒——蓝色巨人IBM发布新传输技术 15核芯片+数据平台,Intel软硬兼备的Hadoop战略 Facebook以160亿美元收购50名员工、4.5亿月活跃用户的WhatsApp 2014年全美最吃香职业TOP100,程序员排第一 LinkedIn向所有用户开放博客发布平台 Google与Facebook的产品研发之道 小米海外扩张第一步 红米进军新加坡 Google I/O大会时间已定,Google Glass真的来了? 精英团队PK全能型数据科学家,拼的可不只是数量 专攻移动支付?PayPal将面向全球开放移动SDK CoconutKit:iOS开发必备的开源组件库 个人隐私是如何“泄漏”的:国内外互联网企业隐私策略对比 惠普2014年Q1财报:净利润同比增16% PC业务逆势好转 “阅后即焚”挖谷歌墙角,GAE技术大牛跳槽Snapchat 日800万访客、20万RPS网站的5个9可用性架构 程序员想找好工作?那就学好Linux吧! 一周消息树:开源专家袁萌,国产COS操作系统是“杂种”,不是中国软件梦 移动周报:对话智能硬件云服务平台Yeelink Node.app:用Node.js API开发iOS“原生”应用 Google Project Tango:能3D捕捉的智能手机 成功打造Evernote API生态系统的五大经验 推荐一些适合初学者看的书吧 一家位于Montreal, Canada的公司,求购一个程序 如何保存UNICODE的字符串到硬盘上 如何将HTML文本直接显示在CppWebBrowser中?(不使用临时表) 如何保存UNICODE的字符串到硬盘上 redhat第4第5两个iso文件是做什么的 关于jsp做客户端调用ejb的问题?????望各位兄弟们救救我吧!!!!! COOL!将所有菜单设置为半透明的代码(只适用于WIN2000以下版本) 请问谁知道如何用jakarta-jmeter进行压力测试? 如何判断文件夹是否存在 在Win2K Server安装Oracle817时,没有安装数据库,后在创建数据库时出现"ORA-12560:TNS:协议适配器错误"... 请教.net服务器问题 解决这个问题,给你200分!!!!!!!!!!(回头追加给你!) 我是初学者,请问.net framework先进性在哪里? 有谁试过用JAVA编FTP软件? 很简单的listBox问题,HELP 今年大四,现在找工作,求助,我怎么样………UP有分。 寻找!! IE的文本输入框,输入一字符会联想,请问怎样去掉这个联想?(Win2K) 哪位大俠能賜教 哪位大俠能賜教 你们说VC到底要学些什么?VC更偏底层,总做这种纯技术总也做不完。迷茫~~~ 请问,在Oracle里建trigger是不是有什么说法呢?一个正常的不能在正常的trigger在Oracle里运行也说compilation errors. 请教:提取字符串里每个字符首字母,谢谢!!! aa模块代码 关于强烈要求恢复可用分增长、可用分转移、非技术区得分转换为可用分的建议!! SOS:如何找到窗口中多个进程其中我所需要的那一个? SOS:如何找到窗口中多个进程其中我所需要的那一个? 笑的人再发几个 query1.next是将指针移向下一条,啊向上条一记录是用什么命令呢? 对话框中使用工具栏如何进行更新? 关于文件指针的问题 ASP中SELECT 查询中前几条的查询如:TOP 的用法哪位讲解一下. 如何查找到两个不同数窗的不同数据 诚招ASP老师一名(请版主不要删) 提问!(欢迎讨论) 停电重启 原来已经编译通过的程序,再重新编译竟然出现了150个错误 一个很奇怪的想法 请问怎么转换以空格为分割符的文本文件转换为以TAB为分割符的文本文件?急! WIN2000下怎么设CLASSPATH (散分):BDE,ADO,dbExpress的前景如何? 关于VB调用asp的问题 如何关闭office2000文件优化器? 怎么知道combobox选中的序号如combobox.item[i]中的i 怎么知道一张图片的有效宽度及长度 浙大1082的几个疑问 系统快成功了,有个大问题 请问98是不是自带了一个局域网聊天工具? 求助!VC中起动现有的Windows程序的语句。谢谢! 请教:如何在DATAGRID控件的行标头上,写上1,2,3....的顺序号?? 请C++语言高手回答:一个有关C++语言派生的简单问题! 不能用汉字制作电脑系统,为什么不能用汉语注音符号做电脑系统呢?比如VB语言的“input”可以用“ㄕㄨˉㄖㄨˋ”(就是输入的注音符号,拼音‘shū rù’翻译过来就是了) PS和AI实质上的区别是什么.为什么PS那么普遍的使用.AI的使用面很小.他们有什么区别. 遗失的幸福用英语怎么说 续写句子 书是钥匙,能开启智慧之门; 书是良药,__________; 书是_____,__________;在_____ 填 我的书屋,我的梦 .400字作文 我的书屋,我的梦征文怎么写?结合新中国成立65周年 左边一个米右边一个少是什么字 求,写压岁钱的作文 写出歇后语的后半部分.矮子坐高登—()稻草人救火—()炒咸菜放盐巴—()擦胭脂进棺材—()各位...写出歇后语的后半部分.矮子坐高登—()稻草人救火—()炒咸菜放盐巴—() 左边一个米字 右边一个甚字 是什么字 骑马与砍杀和骑马与砍杀战团哪个好玩,有什么不同? 歇后语棺材头上雕花的下一句是什么? This shirt is cheaper ____ that one.填上合适的单词. 毛泽东的座车变迁史的第2题怎么写 18 ST.LEONARDS CL.NOBLE PARK VIC 3174 AUSTRALIA这个英文地址翻译成中文是什么意思 一个者字下面一个羽字读什么一个者字下面一个羽字读什么 英语翻译当你还是很小的时候.妈妈花了很多时间教你用勺子、用筷子,教你怎麼吃饭.教你穿衣服、系鞋带、扣扣子.教你洗脸,梳头发.我爱我的妈妈!你在渐渐长大,而妈妈渐渐的老了有一天 当 有哪个英语单词是9个字母,且第2个是l, 表事拼搏的词 毛泽东的座车变迁史练习题的第1小题怎么写? 请你更换下面各单词中的某个字母,使其成为另一个单词求大神帮助safe 、 meet 、road、hand 快来 急 食盐在20摄氏度,100摄氏度时的为36克,40克.若将100克水在100摄氏度时制成饱和溶液,溶解食盐——克,从中析出食盐固体_克;若降降温后所得溶液保持20克,50克水,则析出食盐的质量分别为_克,_克 《毛泽东的座车变迁史》 1、说说下列词语在文中的意思.横空出世 鲜为人知 y=lg(mx2-mx+1),要使定义域为R,求m 取值范围? 韩国蔚山与美国底特律都是著名的汽车城,它们有何异同? 毛泽东的座车变迁史:“这辆加长型‘大红旗’矫车堪称‘国宝’”.作者为什么要赞叹这辆车堪称“国宝”? 【欢乐女神】表达了作者什么样的精神 世界上纬度最高,跨经度最多大洲和大洋分别是?北冰洋和南极洲共同的特点? 要一篇精彩!的我的书屋我的梦作文,500字以上 欢乐女神蝶的描写片段 七年级上册历史的三次改革都起到了怎样的作用 1、桂林山水美得像() 2、他听到()从那边传来 3、大海里的鱼非常多(改夸张句) 欢乐颂中的欢乐女神是什么含义 左边一个月字旁,右边一个会是什么字? 大海掀起巨浪改成夸张句十万火急啊 大海里的鱼非常多.改夸张句 左边一个女子 右上边一个公下面是一个羽 这个字怎么读啊!急 最长的英文单词是什么求大神帮助 大海里的鱼很多 改成夸张句 英语翻译麻烦翻一下(谢绝翻译器答案 ):"欢迎留下你的脚印"(就是欢迎你留言的意思) 改夸张句:大海里的非常多. 语文人教版四年级上册语文园地七的习作怎么写? 英语翻译1.上课认真听讲2.课后认真完成作业3.考前认真复习4.有恒心,有毅力,敢于钻研5.遇到问题及时询问老师取得好成绩就这么简单! 最长的英文单词是什么?求大神帮助 大海里的鱼非常多.(改为夸张句) 人工智能与智能的定义和本质区别是什么? Sydney Australia是什么意思 Welcome to china when you have free time,I will be your guide for 10 pounds one hour.Is that OK? 英语翻译我所居住的地方是中国冬天最多雪的地方,但今年雪下的特别少.很多国家都拍了以A 为主角的电影 ,但是我觉得J扮演的最形象.我也十分欣赏J.谢绝翻译软件 australia,sydney,amazing什么意思? 海洋里的鱼非常多.(改为夸张)只要写出鱼多就可以了! 检查一下我做的对不对31、I was bad at English last term, I will try my best to learn it _D_____. A. from then on B. from last term C. from on D. from now on 32.—I think that China will win the World Cup one day. —I__A_____. The Chine 60摄氏度时,将30克硝酸钾溶于210克水中,该溶液中溶质的质量分数为---,若将该溶液平均分成三等份,则:(1)取第一份,温度升高到90℃,此时溶液溶质的质量分数为---.(2)取第二份,要使溶液的 Sydney Australia 帮我检查一下我做的对不对-1 I called____you five times yesterday.Where are you?(at)2 It's too late to go to the pictures.Why don't we call the whole thing____?(out)3 We called____to him but he could not hear us.(out)4 I called____the post 上面一个羽字,下面一个佳字.是什么字拼音字母拼 北京和澳大利亚的sydney的四季有什么不同 恐怕像这样的黑色鞋子在两个月前就不流行了.用英文翻译 AI和PS的区别 Sydney.Australia用英语怎样读?
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘