<第一部分 Inside 無形的枷鎖>
PB實在太古老了,長久的積澱變成了沉重的包袱,像是一個無形的枷鎖制約着工具的發展。
前言
PowerBuilder作為開發工具退出一線行列已經很久了,在2019年來談這樣一款老舊的程式設計工具是否有意義?誠然,PB有着太多硬傷,但還是有它的用武之地的。而且今天講的這個“新思維”大部分内容是我在其它地方沒有見過的,包含一些比較新的思想,但願能夠給各位讀者帶來耳目一新的感覺和有價值的參考。
由于内容比較多,打算合起來作為一個庫,名字叫PowerPlume,中文為“孔雀翎”,古龍書中強大又美麗的武器。
PowerBuilder程式設計新思維1:擴充(Lua)
PB環境是封閉的,導緻有些部分的能力極弱,依賴開發各類DLL和擴充(PBNI)。把腳本語言引擎引入到PB中,有着很多的現實意義,最大的好處就是能夠直接利用腳本語言的各類資源與源碼,不用再重複開發。
常見的腳本語言有JS、Python、Ruby等,為什麼選擇Lua?因為小、因為快。JS由于曆史原因,太龐大了。Python和Ruby也不是很小巧。而且環境配置複雜。Lua小巧,接口也很友好,資源也豐富。
接口方面,選擇PBNI而不是直接使用DLL,是因為需要處理一些指針和支援PowerObject,總體與LuaApi基本一緻。
global type n_lua from nonvisualobject native "pblua105.dll"
public function long register(string name, powerobject obj)
public function long setglobal(string name)
public function long getglobal(string name)
public function long setfield(long idx, string key)
public function long getfield(long idx, string key)
public function long pushnil()
public function long pushboolean(boolean value)
public function long pushlong(long value)
public function long pushdouble(double value)
public function long pushstring(string value)
public function long pushpowerobject(powerobject value)
public function long toboolean(long idx, ref boolean value)
public function long tolong(long idx, ref long value)
public function long todouble(long idx, ref double value)
public function long tostring(long idx, ref string value)
public function long topowerobject(long idx, ref powerobject value)
public function boolean isboolean(long idx)
public function boolean islong(long idx)
public function boolean isdouble(long idx)
public function boolean isstring(long idx)
public function boolean ispowerobject(long idx)
public function boolean isnil(long idx)
public function boolean istable(long idx)
public function long spop(long n)
public function long scopy(long idx)
public function long sinsert(long idx)
public function long sremove(long idx)
public function long sreplace(long idx)
public function long sgettop()
public function long createtable(long arr, long rec)
public function long settable(long idx)
public function long gettable(long idx)
public function long setmetatable(long idx)
public function long nextkey(long idx)
public function long docall(long args, long results)
public function long dofile(string path)
public function long dostring(string str)
public function long enablecall(boolean ui)
end type
最先實作的功能是在Lua中很簡單,PB卻無法提供的功能——HashTable。
執行個體:function integer of_map_set (string as_table, string as_key, powerobject an_value)
在Lua接口基礎上,添加了pushpowerobject這個接口,以處理PB對象。
int ret
ret = api.getglobal(as_table)
if (ret = LUA_TNIL) then
api.createtable(0, 0);
elseif (ret <> LUA_TTABLE) then
return FAILURE
end if
api.pushstring(as_key)
api.pushpowerobject(an_value)
api.settable(-3);
if (ret = LUA_TNIL) then
api.setglobal(as_table)
end if
return SUCCESS
其次,必須利用Lua中比較成熟的資源,可以在https://luarocks.org/上查找下載下傳數較多的子產品,放入lib\lua目錄下即可require。需要注意的是我們使用的是最新的Lua53,有些庫可能不相容。在源碼中已經放入socket(http,ftp,stmp),xml,json庫。後續會陸續補上相關的封裝接口。
執行個體:使用cjson子產品解析json
1 string res
2
3 i_lua.api.dostring("return require('cjson')")
4 i_lua.api.pushstring('decode')
5 i_lua.api.gettable(-2)
6
7 if (not i_lua.api.isfunction(-1)) then
8 messagebox("","error")
9 end if
10
11 i_lua.api.pushstring(mle_json.text)
12 i_lua.api.docall(1,1)
13
14 i_lua.api.pushstring("sites")
15 i_lua.api.gettable(-2)
16
17 string key,val
18 integer idx
19 idx = i_lua.api.sgettop()
20
21 i_lua.api.pushnil()
22 do while i_lua.api.nextkey(idx)<>0
23 i_lua.api.pushstring("name")
24 i_lua.api.gettable(-2)
25 i_lua.api.tostring(-1, val)
26 i_lua.api.spop(2)
27 tv_1.InsertItemFirst(0,val,1)
28 loop
29
30 i_lua.api.spop(3)
另外,在建構PowerPlume這個庫的時候,整體架構在Lua這個子產品之上,主要是利用其HashTable這個功能。
效果及源碼

源碼: PowerPlumeDemoV0.1.1.rar
提供了PB10.5 PB11.5 PB12.5三個版本
<本節完>