




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、PBNI 是Powerbuilder 的本机扩展,是很强大的东东,最近因为工作需要,稍作了点研究,希望对未做过PBNI的朋友,有所帮助。用最简单的的话来讲,(不准确),就是Java ,C+ 里可以加载PB的虚拟机,利用PB的对象,语言,主要是利用PB在某些方面的强大功能,让他们能很好的结合。PB 安装目录 SDK下的文件非常重要,要阅读下PB自带的帮助文档。Powerbuilder9 的版本只支持 vs6,10.5的最高支持到VS2005 ,如果要想让PBNI 支持到VS2008,并且集成到appwiz里,需要手动来做。%SybasePb105PowerBuilder 10.5SDKPBNIW
2、izardsVCWizardsPBNIWizard8,此目录下的deploy.bat 文件有时执行不一定成功,手动就可以,按照里边的步骤做,做完后,%SybasePb105PowerBuilder 10.5SDKPBNIWizardsVCProjects 8.0,这个目录下的文件PBNIWizard.vsz 文件用UE打开,将8.0 改为9.0 ,再复制到相应目录,就可以在VS2008里用向导创建PBNI工程了。还有一点要提醒的是,一定要使用向导来创建PBNI,否则很容易挂哦PowerBuilder 9开发技术讲座 PowerBuilder Native Interface(PBNI)Powe
3、rBuilder 9现在对于其他开发语言的支援,有了全新的突破,在以往使用PowerBuilder开发程式时,要和C+或是Java程式互通有无是有一些折衷的办法,但是总是没有办法做到简易而且全面性的支援。现在只要透过PowerBuilder 9的PBNI技术,就可以让PowerBuilder的程式呼叫Java,或是在一个C+的程式中引用PowerBuilder NVO物件函数。 以往的PowerBuilder程式只能够透过外在函数呼叫的方式来存取C/C+的函数,但在PowerBuilder 9.0之中扩增了一项强而有力的介面PowerBuilder Native Interface,简称PBN
4、I。透过PBNI的开发方式,PowerBuilder开发人员不仅可以使用物件导向的方式来存取C/C+函数,而且还可反向地让C/C+程式呼叫PowerBuilder之中的物件,达到应用程式的整合。更甚者,在藉由JNI与PBNI两者的结合,Java应用程式也可双向地与PowerBuilder程式沟通。 何谓PBNI在谈什么是PBNI之前,我们先来谈谈下面三个问题: 1.开发人员有办法用PowerBuilder程式呼叫C或是C+的程式吗? 2.开发人员有办法用PowerBuilder程式呼叫一些外部元件像是Java EJB元件、 Web Service元件、Java Class程式等诸如此类的元件吗
5、? 3.开发人员有办法用反过来,用C或是C+呼叫已经使用PowerBuilder开发好的程式吗? 上述三个问题,在过去的PowerBuilder其实都可以做到某种程度的地步,只是都有些问题。传统上使用PowerBuilder开发上述的程式时,如果要呼叫C或是C+ 的程式,是可以使用宣告外部函数的方式来使用一个已经撰写好的DLL函数, 例如: FUNCTION ulong GetSysColor (int index) LIBRARY "USER32.DLL” FUNCTION boolean sndPlaySoundA (string SoundName, uint Flags) L
6、IBRARY "WINMM.DLL" 可是如果是下面的程式呢: BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam); 这个可是个大问题了,因为这个Windows DLL Function中会用到所谓的Callback 函数的技术,所谓的Callback Function指的是今天有A和B两个物件,在程式中A物件呼叫B物件的Function,而在该B物件的Function又会回头呼叫A物件的其他Function,这就叫Callback。在PowerBuilder呼叫C的Function后,在这个C的Function中
7、要再回头呼叫PowerBuilder的函数是不可能用引用外部函数的方式来达到这个目地的。除了Callback Function使用困难之外,使用外部函数也有资料型态的限制,以及没有办法使用物件导向的方式开发等种种的困难及问题。 再来谈谈PowerBuilder呼叫外部的元件的方法,在以前能够让PowerBuilder呼叫EJB元件,就只能透过一些协力厂商开发的COM Bridge,让PowerBuilder程式透过COM元件来呼叫Java程式。至于要让Java或是C+来呼叫PowerBuilder 程式的话,过去最常见的方法就是把这个PowerBuilder的程式包装成为OLE automat
8、ion server。这些方法都不是一个真正解决的好方法,说穿了,这些方法跟本就没有办法直接和PowerBuilder的核心PowerBuilder Visual Machine做沟通,所以在过去的版本的PowerBuilder,是一直有这种和其他语言程式不能沟通的困扰,这也是大家一直认为,PowerBuilder是一个封闭不开放的开发工具。 PowerBuilder 9这个版本有几个突破性的技术,而PBNI就是其中一个。所谓的PBNI (PowerBuilder Native Interface),指的是PowerBuilder提供一个原生介面(Native Interface),透过这个介
9、面可以使得PowerBuilder提高了对其他程式语言的扩展能力,比方说透过该介面可以存取任何类型的外部应用应用程式,或是让外界其他的程式语言存取或是呼叫PowerBuilder开发的程式,下面是一个简单的PBNI的示意图: 此主题相关图片如下:1.jpg在上面这张图中,PBNI提供了两道让外界可以和PowerBuilder核心(PBVM)的介面窗口,第一个对外的窗口是指在图的右半边,我们可以开发PB Extension, PB Extension其实最后会变成DLL,透过该技术,C或是C+的DLL程式可以包装成为一个PBD的档案,而该PBD的档案就可以在开发程式时,加到Library Sea
10、rch Path中,让PowerBuilder直接存取PBD里的物件函数,你可以把它当作是一个很像PowerBuilder NVO的东西来对待它。第二个对外的窗口是指在图的左半边,你可以把PowerBuilder Virtual Machine 内嵌到一个C+的应用程式中, 在C+程式中就可以直接呼叫PowerScript Function。 PBNI的元素PBNI提供了一些基本的元素,透过这些元素,程式开发人员可以快速的引用外部程式语言,下面是常见到的PBNI元素: ? PBNI提供的介面(Interface): ? IPB_VM:这个介面的作用,在于当你要用C+或是其他的程式语言来呼叫Po
11、werBuilder开发的程式,或是你希望要和PowerBuilder的核心PBVM进行互动,或是沟通协调,你可以使用这个介面。 ? IPB_Session:这是一个抽象的介面,这个介面可以用来定义诸如存取PowerScript里面的资料、建立PowerBuilder物件和呼叫PowerScript函数操作的方法? IPB_Value:这个介面你可以把它想像成是它就是代表PowerBuilder的值。这些值可以是PowerBuilder的标准资料型态,例如String、Long、 Integer、Char等等。所以这个介面提供了关于每个变数的资讯,包括变数的类型、标记、存取权限(Public、
12、Private和Protected)、变数值或参数存取方式(例如Call by Value或是Reference)。 ? IPB_Arguments:这个介面可以让使用者在PowerBuilder VM和PB Extension间传递参数。 ? IPBX_NonVisualObject和IPBX_VisualObject:这两介面很意思,因为它们可以在C+程式中实作出来,而且是放在PB Extension里面,你在PowerBuilder中就可以用PBD的方式看到你实作出来的物件,而要写这些可见或是不可见的物件,靠的就是IPBX_NonVisualObject和IPBX_VisualObjec
13、t介面。 ? IPBX_Marshaler:这个介面是当你要出一个PB marshaler extension 时, 一定要实作出IPBX_Marshaler这个介面。这个介面尤其是你要由PowerBuilder呼叫Java程式时,一定要用到的一个介面。 ? PBNI提供的Structures: ? PBCallInfo:这个Structure可以在开发PBNI程式时,让PBNI和PowerBuilder之间呼叫的函数保持参数和回传值的资讯。如果要存取在PBCallInfo中的资讯,可以使用IPB_Arguments介面来获得PBCallInfo。 ? PBArrayInfo:PBArrayI
14、nfo是一个C+的structure,这个Structure可以在阵列中保持一些资讯。 ? PBNI提供的Globle Function: 如果你要写一个PowerBuilder extension的程式(说穿了就是用C+写一个DLL档啦),这个物件必须要汇出两个Global Functions,让这个程式可以内嵌 PowerBuilder VM并且建立实体出来。下面是PBNI提供的Globle Function: ? PBX_GetDescription() ? PBX_CreateNonVisualObject() ? PBX_CreateVisualObject() ? PBX_Invo
15、keGlobalFunction() ? PBNI提供的Helper classes: Helper Classes指的是一些辅助的类别物件,PBNI提供像是PBObjectCreator、 PBArrayAccessor和PBEventTrigger等辅助类别,透过这些辅助类别物件可使PBNI在开发上更简单。 PBNI的开发方式在了解PBNI有那些元素后,读着应该也了解到何谓PBNI,并且知道PBNI能帮我们做什么。在针对不同的目地,PBNI也有不同的开发方式,常见的PBNI开发目地为下列四个,在后面的部份会祥细的说明PBNI的开发方式为何: ?建立PB extensions ?建立PB m
16、arshaler extensions ?建立PB visual extensions ?内嵌PBVM到C+的应用程式中建立PB extensions步骤之前有跟各位读者提过,PBNI提供了两个对外的方法,其中一种就是将C或是C+写好的DLL档案,透过PBNI提供的介面来包装成一个PowerBuilder认得的PBD档案,这种方式称之为建立PB Extensions。在开发一个PB Extensions的程式时,我们必须先设想好,最后我们要产生的PBD中,会有那些物件。比方说,我现在手头上正在写一个C+的程式,我希望这个C+的程式最后透过PBNI 的帮助,产生一个PBD档案,而且在这个PBD里
17、面有一个Funtion物件,而这个Function物件会对照于我在C+里面写好的Function,让我只要呼叫该Function 物件,就等于是执行C+里的程式。刚才的设想中,开发的步骤如下: 1.使用C+的开发工具建立一个C+专案。 2.在C+的程式中,汇入PBNI SDK提供给C+的相关表头档(h档案)。 3.在C+的程式中,透过PBX_GetDescription()这个PBNI提供的函数,告知到时后会汇出一个Globle Function。 4.因为要做的是一个Globle Function物件,所以在C+的程式中,透过PBX_InvokeGlobalFunction()这个PBNI提
18、供的函数,实作该Function的程式出来。 5.将开发好的C+程式编辑成DLL档。 6.透过PBNI提供的pbx2pbd90.exe小工具,将这个DLL档案转换为PBD 档。 7.打开PowerBuilder后,将这个PBD档加到Library Search Path中。 8.开发相关的PowerBuilder程式,并且呼叫这个PBD档的Globle Function。 定义要汇出的物件类别在上述的步骤中,PBX_GetDescription()这个PBNI提供的函数是一定要有的,因为这个函数是用来产生相关的类别定义,而这个类别定义最后会在将DLL档案转换成PBD档时,跟据你在PBX_Get
19、Description()函数中的定义,产生相对应的PowerBuilder物件。下面在C+的程式,最后会产生一个PB的Globle Function物件,这个Globle Function物件名称是GetUserName(),而它的回传值是String资料型态: PBXEXPORT LPCTSTR PBXCALL PBX_GetDescription() static const TCHAR desc = "globalfunctions n" "function string GetUserName()n" "end globalfunct
20、ions n" ; return desc ; 再举一个例子,下面写在C+里的PBX_GetDescription()函数程式,最后会产生一个PowerBuilder的可视物件flagext,在这个可视物件中,有两个事件为分别为onclickEvent和ondoubleclick Evnet;在可视物件中,还有两个物件Function settext(string txt)和setflag(int flag): PBXEXPORT LPCTSTR PBXCALL PBX_GetDescription() static const TCHAR desc = "class fl
21、agext from usero b j e c tn" "event int onclick()n" "event int ondoubleclick()n" "subroutine settext(string txt)n" "subroutine setflag(int flag)n" "end classn" ; return desc; 实做类别物件程式码之前提到的步骤中,除了PBX_GetDescription()之外,我们还会步骤四中看到一个PBNI提供的Function
22、,叫PBX_InvokeGlobalFunction(),这是因为我们要实作出Globle Function的程式,所以就必须要使用PBX_InvokeGlobalFunction()函数;相同的道理,如果在PBX_GetDescription()中我们准备建立的是一个NVO物件,那就要用PBX_CreateNonVisualObject()函数实作出NVO物件的程式;如果在PBX_GetDescription()中我们准备建立的是一个可视的PowerBuilder物件,那就要用PBX_CreateVisualObject()函数实作出这一个可视物件的程式。下面是一个在C+中使用PBX_Inv
23、okeGlobalFunction()来实作出一个Globle Function程式的例子: PBXEXPORT PBXRESULT PBXCALL PBX_InvokeGlobalFunction ( IPB_Session* pbsession, LPCTSTR functionName, PBCallInfo* ci ) if ( strcmp( functionName, "getusername" ) = 0 ) CWinAPI *WinAPI = new CWinAPI( pbsession ) ; WinAPI->PBNIGetUserName ( ci
24、 ) ; if ( WinAPI != NULL ) delete WinAPI ; return PBX_OK ; ; return PBX_E_NO_SUCH_CLASS ; 在上面的程式码中,读者可以发现,程式PB Extension和PB的核心PBVM的沟通是透过IPB_Session这个指标变数来保持C+和PowerBuilder程式的连结,而在PBNI和PowerBuilder之间呼叫的函数保持参数和回传值的资讯就是透过之前介绍的PBCallInfo这个指标结构来保存,下面是PBVM和PB Extension之间的关系示意图: 此主题相关图片如下:2.jpg下面是完整的程式码,这个
25、程式码中,在pbniwinapi.cpp程式实作出类别CWinAPI,在这个Class中,有一个PBNIGetUserName()函数会透过Windows 作业系统的API取得电脑的使用者名称,而main.cpp中会汇出一个PB Globle Function叫GetUserName(): pbniwinapi.cpp #include <WINDOWS.H> #include <stdio.h> #include "PBNIWINAPI.h" CWinAPI:CWinAPI( IPB_Session * pSession ) : m_pSessio
26、n( pSession ) CWinAPI:CWinAPI(void) void CWinAPI:PBNIGetUserName ( PBCallInfo *ci ) LPTSTR lpszSystemInfo; DWORD cchBuff = 256; TCHAR tchBuffer1024; lpszSystemInfo = tchBuffer; GetUserName ( lpszSystemInfo, &cchBuff) ; ci->returnValue->SetString ( lpszSystemInfo ) ; void CWinAPI:Destroy()
27、delete this ; main.cpp #include <windows.h> #include <pbext.h> #include "pbniwinapi.h" BOOL APIENTRY DllMain( HANDLE hModule, DWORD reasonForCall, LPVOID lpReserved ) switch( reasonForCall ) case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCE
28、SS_DETACH: break; return TRUE; PBXEXPORT LPCTSTR PBXCALL PBX_GetDescription() static const TCHAR desc = "globalfunctions n" "function string GetUserName()n" "end globalfunctions n" ; return desc ; PBXEXPORT PBXRESULT PBXCALL PBX_InvokeGlobalFunction ( IPB_Session* pbses
29、sion, LPCTSTR functionName, PBCallInfo* ci ) if ( strcmp( functionName, "getusername" ) = 0 ) CWinAPI *WinAPI = new CWinAPI( pbsession ) ; WinAPI->PBNIGetUserName ( ci ) ; if ( WinAPI != NULL ) delete WinAPI ; return PBX_OK ; ; return PBX_E_NO_SUCH_CLASS ; 产生PowerBuilder延伸物件在上面的C+程式完成后,
30、便可以编辑一个DLL档案,可是这个DLL档案并不是要让PowerBuilder直接拿来用,因为这样子一来,就又回到使用外部函数的做法,比较好的方式是要产生PB Extension,也就是说把这个DLL再包一层, 用一个PBD帮这个DLL档案做一个PowerBuilder看的懂的外皮,然后让PowerBuilder透过PBD来认识你写好的DLL程式。 在PowerBuilder9安装目录下%Sybase9%PowerBuilder 9.0SDKPBNI,你会发现有一个叫pbx2pbd90.exe的档案,如果要帮DLL再包一层PBD档案,必须透过pbx2pbd90.exe这一个档案,它的语法如下:
31、 pbx2pbd90 your.pbd your.dll 比方说有一个DLL档案叫pbniwinapi.dll,要把这个档案转成PBD档,就可以这样子下: pbx2pbd90 pbniwinapi.pbd pbniwinapi.dll 如此一来,它会产生pbniwinapi.pbd档,并且根据你原先写在C+程式中的PBX_GetDescription()函数内容,在这个PBD档案产生出相对应的PowerBuilder 可以认得的物件,让开发人员取得该物件后,用PowerBuilder原生语法PowerScript就可以呼叫该物件的函数来做事情。 下图是一个产生PBD档案的示意图: 此主题相关图
32、片如下:3.jpgPowerBuilder使用PB Extension开发程式产生好PB Extension后,读者一定很好奇两件事,第一件事就是我可不可以只要用产生好的PBD物件,而把原来的DLL档案删除?答案是不行,因为PBD物件只是一个帮DLL档案产生出来的一个空壳,借由这个PBD空壳,PowerBuilder才行使用DLL程式;第二个问是就是使用PB Extension的步骤为何?其实使用PB Extension很简单,只要把它当作是一般的PowerBuilder程式物件来用就可以了,下面是它的使用步骤: 1.将产生好的.PBD档案加到你的PowerScript Target,也就是把
33、这个PBD档案加到Library Search Path中。 2.将PB extension DLL档案拷贝到开发程式目录下面3.使用PowreScript语法呼叫物件的函数假设现在有一个PB Extension档案加到Library Search Path中,在这个PBD里面有一个NVO物件叫SimpleExt,在该物件有一个hello()函数,在PowerBuilder的程式中,就会这样子写: SimpleExt ext ext = create SimpleExt String str Str = ext.hello( “Hello, whats your name? ”) Messag
34、ebox( “hello ”, str); 下面是这次呼叫PB Extension程式的流程示意图: 此主题相关图片如下:4.jpg内嵌PBVM 在一开始的时后提到,PBNI提供了两扇对外的门户,一个是可以将C或C+的程式转成PB Extensions,也就是转成PBD的方式;另一个对外的门户是可以在C+程式中内嵌PBVM。关于第一种方法在上面介绍过了,而接下来就是要介绍第二种对外的门户,内嵌PBVM。 相信读者在开发其他的语言程式时,一定时常会有一个希望:啊,如果我的Java程式可以使用DataWindow物件就好了。 ;或是上次的专案我已经用PowerBuilder开发好一些模组,在这次的
35、C+专案中,真不想再写一次。 如果读者有这种需求,这时后最好的方式,就是使用内嵌PBVM的作法, 透过这个PBNI的技术,C+的程式也可以顺利的呼叫PowerBuilder开发好的物件,具体的开发方式为: 1.在C+程式中载入PBVM。 2.在C+程式中利用IPB_VM介面来取得C+和PB的连结。 3.建立该PBL或是PBD的Library Session(其实也是透过IPB_Session介面)。 4.在C+里面建立这个NVO物件的实体。 5.呼叫这个NVO物件的Function。 举例来说,我有一个trypbni.pbl,在这个PBL档案中,有一个NVO物件叫作n_ben物件,在该物件中有
36、一个foo()函数,现在在开发一个C+的程式时, 就可以把PBVM给内嵌到C+程式中,并且在C+程式呼叫这个n_ben.foo()函数,相关的的部份程式码如下: trypbni.cpp 1. int main(int argc, char* argv) 2. 3. HINSTANCE hinst = LoadLibrary("pbvm90.dll"); 4. P_PB_GetVM getvm = (P_PB_GetVM)GetProcAddress(hinst, "PB_GetVM"); 5. IPB_VM* vm = NULL; 6. getvm(&vm); 7. static const char *liblist = "trypbni.pbl" ; 8. IPB_Session* session = NULL; 9. vm->CreateSession("trypbni", liblist, 1, &session); 10. pbgroup group = session->FindGroup("n_ben", pbgroup_usero b j e c t); 11. pbclass clz = s
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 国企民营自然人合同协议
- 工程中介提成合同协议
- 城建集团供货合同协议
- 垫资工程利息合同协议
- 工程分包合同补充协议
- 地产中介佣金合同协议
- 外教教师聘用合同协议
- 土地互换合同协议模板
- 外协加工协议合同协议
- 商铺合同更改协议书范本
- 会计记账服务合同
- 四下第五单元课件
- 【教案】Unit+4+My+Favourite+Subject大单元整体教学设计人教版英语七年级上册
- 出租车驾驶员解约合同范本
- 1《氓》公开课一等奖创新教学设计统编版高中语文选择性必修上册
- 江苏省苏州市2023-2024学年高一下学期期末考试化学试题(解析版)
- 新疆历史印记课件
- 机械加工厂劳务派遣合同书(标准版)
- 离职证明(标准模版)
- 烤肠机投放协议书范本
- 2025届辽宁省辽阳市重点中学高三第二次联考生物试卷含解析
评论
0/150
提交评论