Module BaseClass - With JSON und Runtime (Module as Object)
Posted: Thu Aug 24, 2017 11:57 am
The base is the same as the Module BaseClass. But uses the JSON and Runtime library of Purebasic to initialize the class.
For initialization, the macro InitClass(Interfacename, ...) is called at the end of the module.
All procedures for the interface are implemented using the 'Runtime Procedure MethodName(* this ...)'.
The procedure names 'Runtime Procedure Initialize(* this ...)' and 'Runtime Procedure Dispose(* this ...)' are reserved and are added automatically.
By using the Library JSON and Runtime the Execute would of course be indicated and the license information must be specified
Therefore, I will continue to maintain both modules, with and without JSON.
Thanks to GPI for nice idea with JSON library
Update v2.02
- Cleanup Code
Update v2.03
- Optimize check interface
Update v2.05
- Change internal Initialize and Dispose from list to array to avoid thread blocking
'Modul_BaseClassJS'
For initialization, the macro InitClass(Interfacename, ...) is called at the end of the module.
All procedures for the interface are implemented using the 'Runtime Procedure MethodName(* this ...)'.
The procedure names 'Runtime Procedure Initialize(* this ...)' and 'Runtime Procedure Dispose(* this ...)' are reserved and are added automatically.
By using the Library JSON and Runtime the Execute would of course be indicated and the license information must be specified
Therefore, I will continue to maintain both modules, with and without JSON.
Thanks to GPI for nice idea with JSON library
Update v2.02
- Cleanup Code
Update v2.03
- Optimize check interface
Update v2.05
- Change internal Initialize and Dispose from list to array to avoid thread blocking
'Modul_BaseClassJS'
Code: Select all
;-Begin Module BaseClass (JS)
; Comment : Module as Object - With JSON und Runtime
; Author : mk-soft
; Version : v2.05
; Created : 23.08.2017
; Updated : 24.08.2017
; Link DE : http://www.purebasic.fr/german/viewtopic.php?f=8&t=30331
; Link EN : http://www.purebasic.fr/english/viewtopic.php?f=12&t=69033
; ***************************************************************************************
DeclareModule BaseClass
; ---------------------------------------------------------------------------
; Internal Class Manager
Prototype ProtoInvoke(*This)
Structure udtInvoke
*Invoke.ProtoInvoke
EndStructure
Structure udtClass
Array *vTable(3)
Array Initialize.udtInvoke(0)
Array Dispose.udtInvoke(0)
EndStructure
Structure udtClasses
Map Entry.udtClass()
EndStructure
Global Class.udtClasses
; ---------------------------------------------------------------------------
; BaseClass declaration
Structure sBaseSystem
*vTable
*Self.udtClass
RefCount.i
Mutex.i
EndStructure
; Public Structure
Structure sBaseClass
System.sBaseSystem
EndStructure
; Public Interface
Interface iBaseClass
QueryInterface(*riid, *addr)
AddRef()
Release()
EndInterface
; ---------------------------------------------------------------------------
Macro dq
"
EndMacro
; ---------------------------------------------------------------------------
; Added New Class
Declare AddClass(ClassName.s, ClassExtends.s, JSValue, Size)
Macro InitClass(ClassInterface, ClassExtends=BaseClass)
Procedure InitClass#MacroExpandedCount()
Protected js, jsvalue, index, size
js = CreateJSON(#PB_Any)
jsvalue = JSONValue(js)
size = SizeOf(ClassInterface) / SizeOf(integer) - 1
Dim iMethode(size)
For index = 0 To size
iMethode(index) = index
Next
InsertJSONStructure(jsvalue, iMethode(), ClassInterface)
AddClass(#PB_Compiler_Module, dq#ClassExtends#dq, jsvalue, size)
FreeJSON(js)
EndProcedure : InitClass#MacroExpandedCount()
EndMacro
; ---------------------------------------------------------------------------
; Macro for init object (short)
Macro InitObject(sProperty)
Protected *Object.sProperty, __cnt, __index
*Object = AllocateStructure(sProperty)
If *Object
*Object\System\vTable = Class\Entry(#PB_Compiler_Module)\vTable()
*Object\System\Self = @Class\Entry(#PB_Compiler_Module)
*Object\System\RefCount = 0
*Object\System\Mutex = CreateMutex()
If Not *Object\System\Mutex
Debug "Error: Class '" + #PB_Compiler_Module + "' create mutex"
FreeStructure(*Object)
*Object = 0
Else
__cnt = ArraySize(*Object\System\Self\Initialize())
For __index = 1 To __cnt
*Object\System\Self\Initialize(__index)\Invoke(*Object)
Next
EndIf
EndIf
ProcedureReturn *Object
EndMacro
; ---------------------------------------------------------------------------
; Macros for init object (advanced)
Macro AllocateObject(Object, sProperty)
Object = AllocateStructure(sProperty)
If Object
Object\System\vTable = Class\Entry(#PB_Compiler_Module)\vTable()
Object\System\Self = @Class\Entry(#PB_Compiler_Module)
Object\System\RefCount = 0
Object\System\Mutex = CreateMutex()
If Not Object\System\Mutex
Debug "Error: Class '" + #PB_Compiler_Module + "' create mutex"
FreeStructure(Object)
Object = 0
EndIf
EndIf
EndMacro
Macro InitializeObject(Object, sProperty=)
If Object
Protected __cnt, __index
__cnt = ArraySize(Object\System\Self\Initialize())
For __index = 1 To __cnt
Object\System\Self\Initialize(__index)\Invoke(Object)
Next
EndIf
EndMacro
; ---------------------------------------------------------------------------
Macro LockObject(This)
LockMutex(This\System\Mutex)
EndMacro
Macro UnlockObject(This)
UnlockMutex(This\System\Mutex)
EndMacro
; ---------------------------------------------------------------------------
EndDeclareModule
Module BaseClass
EnableExplicit
; ---------------------------------------------------------------------------
Procedure AddClass(ClassName.s, ClassExtends.s, JSValue, Size)
Protected r1, RuntimeName.s, MethodeName.s, MethodeID, *addr, index
; Create new class
If FindMapElement(Class\Entry(), ClassExtends)
r1 = AddMapElement(Class\Entry(), ClassName)
Else
DebuggerError("Error BaseClass: Class '" + ClassName + "' - Extends class '" + ClassExtends + "' not exists")
End -1
EndIf
If r1 = 0
DebuggerError("Error BaseClass: Class '" + ClassName + "' - Out of memory")
End -1
EndIf
; Copy extends class and resize vTable
CopyStructure(Class\Entry(ClassExtends), Class\Entry(ClassName), udtClass)
ReDim Class\Entry(ClassName)\vTable(Size)
; Set interface methodes
If ExamineJSONMembers(JSValue)
While NextJSONMember(JSValue)
MethodeName = JSONMemberKey(JSValue)
MethodeID = GetJSONInteger(JSONMemberValue(JSValue))
RuntimeName = ClassName + "::" + MethodeName + "()"
*addr = GetRuntimeInteger(RuntimeName)
If *addr
Class\Entry()\vTable(MethodeID) = *addr
Else
If Class\Entry()\vTable(MethodeID) = 0
DebuggerError("Error BaseClass: Class '" + ClassName + "' - Missing methode '" + MethodeName + "()'")
End -1
EndIf
EndIf
Wend
EndIf
; Added methode Initialize object
RuntimeName = ClassName + "::Initialize()"
*addr = GetRuntimeInteger(RuntimeName)
If *addr
index = ArraySize(Class\Entry()\Initialize()) + 1
ReDim Class\Entry()\Initialize(index)
Class\Entry()\Initialize(index)\Invoke = *addr
EndIf
; Added methode dispose object
RuntimeName = ClassName + "::Dispose()"
*addr = GetRuntimeInteger(RuntimeName)
If *addr
index = ArraySize(Class\Entry()\Dispose()) + 1
ReDim Class\Entry()\Dispose(index)
Class\Entry()\Dispose(index)\Invoke = *addr
EndIf
ProcedureReturn r1
EndProcedure
; ---------------------------------------------------------------------------
Procedure QueryInterface(*This.sBaseClass, *riid, *addr)
ProcedureReturn $80004002 ; (#E_NOINTERFACE)
EndProcedure
; ---------------------------------------------------------------------------
Procedure AddRef(*This.sBaseClass)
LockMutex(*This\System\Mutex)
*This\System\RefCount + 1
UnlockMutex(*This\System\Mutex)
ProcedureReturn *This\System\RefCount
EndProcedure
; ---------------------------------------------------------------------------
Procedure Release(*This.sBaseClass)
Protected index, cnt
With *This\System
LockMutex(*This\System\Mutex)
If \RefCount = 0
cnt = ArraySize(\Self\Dispose())
For index = cnt To 1 Step -1
\Self\Dispose(index)\Invoke(*This)
Next
FreeMutex(*This\System\Mutex)
FreeStructure(*This)
ProcedureReturn 0
Else
\RefCount - 1
EndIf
UnlockMutex(*This\System\Mutex)
ProcedureReturn \RefCount
EndWith
EndProcedure
; ---------------------------------------------------------------------------
Procedure InitBaseClass()
AddMapElement(Class\Entry(), "BaseClass")
With Class\Entry("BaseClass")
\vTable(0) = @QueryInterface()
\vTable(1) = @AddRef()
\vTable(2) = @Release()
EndWith
EndProcedure : InitBaseClass()
; ---------------------------------------------------------------------------
EndModule
;- End Module BaseClass (JS)
; ***************************************************************************************