2011年9月23日 星期五

sizeof in powerbuilder

PowerBuder 開發資料庫應用程式是相當的方便,

但是對於比較低階的資料處理,常常顯得捉襟見肘,

像是有使用到外部 API 時,需要傳遞變數,更多時候都需要一並傳遞該變數的長度,

此時,如果變數是很單純的,例如:char、integer、long 等,

而這些變數長度大致上都可由 help 來查得,

但是對於比較複雜的變數例如 structure 那就真的麻煩了,尤其是 structure 裡面又包 structure,

若是學過 C/C++ 的人都知道裡面有個 sizeof(var) 的函數,

但唯獨在 PowerBuilder 裡面就是沒有,

這也讓開發者真的挫折不少,每次都要自己算。

網路上我找了很久,終於找到可以實用的方法。

所以底下實做一個物件 nvo_sizeof (PB10) 來完成這個 PowerBuilder 所缺少的部份:

1.建立使用者物件 nvo_sizeof
2.將 AutoInstantiate 勾選
3.建立 Instance Variables
Private:
CONSTANT integer SIZE_BOOLEAN  = 1  // Boolean
CONSTANT integer SIZE_CHAR  = 1  // Char
CONSTANT integer SIZE_INT  = 2  // Signed integer
CONSTANT integer SIZE_UINT  = 2  // Unsigned integer
CONSTANT integer SIZE_LONG  = 4  // Signed Long
CONSTANT integer SIZE_ULONG  = 4  // Unsigned Long
CONSTANT integer SIZE_STRING  = 4  // Assume as string pointer
// Supported DataTypes
integer  INTEGER
uint  UINT
long  LONG
ulong   ULONG
char  CHAR
string  STRING
boolean  BOOLEAN



4.建立 10 個 Functions (注意這10個functions是同樣的名字,屬於多型Functions)
public function long sizeof (long data)
Return(SIZE_LONG)
public function long sizeof (unsignedlong data)
Return(SIZE_ULONG)
public function long sizeof (integer data)
Return(SIZE_INT)
public function long sizeof (unsignedinteger data)
Return(SIZE_UINT)
public function long sizeof (character data)
Return(SIZE_CHAR)
public function long sizeof (string data)
Return(SIZE_STRING)
public function long sizeof (boolean data)
Return(SIZE_BOOLEAN)
public function long sizeof (any data[])
// Gives the dimension of an array
// Arguments: Data[] => Array to know the dimension
// Returns: Size of the array
// Notes:
// 1) Supports mixed type arrays (and variable sized strings within the array)
// 2) DOESN 'T support multi-dimension arrays;

long ll_Index, ll_Count, ll_Size = 0

ll_Count = UpperBound(Data)
For ll_Index = 1 To ll_Count
  Choose Case ClassName(Data[ll_Index])
    Case "long"
      ll_Size += SizeOf(LONG)
    Case "unsignedlong", "ulong"
      ll_Size += SizeOf(ULONG)
    Case "int", "integer"
      ll_Size += SizeOf(INTEGER)
    Case "uint", "unsignedinteger", "unsignedint"
      ll_Size += SizeOf(UINT)
    Case "char", "character"
      ll_Size += SizeOf(CHAR)
    Case "string"
      ll_Size += SizeOf(CHAR) * SizeOf(String(Data[ll_Index]))
    Case "boolean"
      ll_Size += SizeOf(BOOLEAN)
  End Choose
Next

Return(ll_Size)

public function long sizeof (variabledefinition vardef[])
// Internal calculations for structure sizes
long ll_Index, ll_Count, ll_Size, ll_Array = 0
ClassDefinition TypeInfo
VariableDefinition VarList[]
VariableCardinalityDefinition VarCarDef
ArrayBounds ArrBounds[]
String ls_typeof

ll_Count = Upperbound(VarDef)

For ll_Index = 2 To ll_Count //ll_Index=1 itself
  VarCarDef = VarDef[ll_Index].Cardinality
  if VarCarDef.Cardinality=BoundedArray! then
    ArrBounds = VarCarDef.ArrayDefinition
    If Upperbound(ArrBounds) = 1 Then
      ll_Array = ArrBounds[1].UpperBound
    elseif Upperbound(ArrBounds) >= 2 then //two dim array
      ll_Array =(ArrBounds[2].UpperBOund)*(ArrBounds[1].UpperBOund)
    End If
  Else //ScalarType! or UnboundedArray!
    ll_Array = 1
  End If
  ls_typeof = lower(VarDef[ll_Index].TypeInfo.DataTypeOf)
  Choose Case ls_typeof
    Case "long"
      ll_Size += SizeOf(LONG) * ll_Array
    Case "ulong", "unsignedlong"
      ll_Size += SizeOf(ULONG) * ll_Array
    Case "int", "integer"
      ll_Size += SizeOf(INTEGER) * ll_Array
    Case "uint", "unsignedint", "unsignedinteger"
      ll_Size += SizeOf(UINT) * ll_Array
    Case "char", "character"
      ll_Size += SizeOf(CHAR) * ll_Array
    Case "string"
      ll_Size += SizeOf(STRING) * ll_Array
    Case "structure"
      TypeInfo = VarDef[ll_Index].TypeInfo
      VarList = TypeInfo.VariableList
      ll_Size += SizeOf(VarList)
    Case Else
      //if just store pointer in pb?? ll_Size+=(4*ll_Array)
      MessageBox( "SizeOf error ", "Type is not supported, possibly variable sized or object type! ",StopSign!,Ok!)
      Return (-1)
  End Choose
Next

Return(ll_Size)

public function long sizeof (powerobject data)
// This function calculates the size of a structure
// The structure can contain simple datatypes (long, integer, boolean), arrays or
// other structures within it
// Arguments: Data => Structure to know the size of..
// Returns: Size of the structure or -1 if error
// Notes:
// 1) Cannot calculate the size of a structure with strings (variable size), for fixed
// sized strings use a char array;
// 2) CAN calculate the size of multi-dimension arrays within the structures

ClassDefinition ClassDef
VariableDefinition VarDef[]

ClassDef = Data.ClassDefinition

if Not ClassDef.IsStructure then return - 1

VarDef = ClassDef.VariableList

Return(SizeOf(VarDef))



使用方式:
nvo_sizeof  ln_size
long ll_size
//假設我有定義一個結構 str_http_header
str_http_header lstr_hdr
ll_size = ln_size.sizeof(lstr_hdr)
MessageBox("str_http_header結構長度" , String(ll_size))


參考來源:http://topic.csdn.net/t/20040811/10/3262788.html

>>>>>>>>>>2011-10-25補充<<<<<<<<<<
這個物件在多 ShareObject 使用下會有問題,
當相同的 ShareObject 建立起超過一個以上時,
呼叫 sizeof 所傳遞的參數會導致出現 null Object 的錯誤發生,
實際的原因尚未明暸,暫時先避開使用。

0 個回應: