Recompile libraries and see changes on the fly
without closing and restarting the host program.
Include:
Code: Select all
EnableExplicit
;Hot Reload DLL
;Platform: Windows OS
;Author: Mijikai
;Version: Draft 1
;It works with a copy of the original library (which is created) either in the same or temp directory.
;The original libraries creation time is monitored to determine if it should be reloaded.
;Functions:
;- hrdLibrary() to add libraries
;- hrdFunction() to determine the function address within a library
;- hrdReload() checks all added libraries and reloads them if needed
;Callback (Init function called when a library is loaded/reloaded):
;Procedure.i Callback(*Name.String,Handle.i,*Parameter)
;EndProcedure
Structure HOT_RELOAD_DLL
handle.i
name.s
copy.s
date.FILETIME
*init
*parameter
EndStructure
Global NewList hrd.HOT_RELOAD_DLL()
Procedure.i hrdReload()
Protected wfa.WIN32_FILE_ATTRIBUTE_DATA
Protected *str
Protected error.i
ForEach hrd()
If GetFileAttributesEx_(hrd()\name,#Null,@wfa)
If CompareMemory(@hrd()\date,@wfa\ftCreationTime,SizeOf(FILETIME)) = #Null
CopyMemory(@wfa\ftCreationTime,@hrd()\date,SizeOf(FILETIME))
If hrd()\handle
FreeLibrary_(hrd()\handle)
DeleteFile(hrd()\copy)
hrd()\handle = #Null
EndIf
If CopyFile(hrd()\name,hrd()\copy)
hrd()\handle = LoadLibrary_(hrd()\copy)
EndIf
If hrd()\handle
*str = @hrd()\name
CallFunctionFast(hrd()\init,@*str,hrd()\handle,hrd()\parameter)
Else
error = #True
Break
EndIf
EndIf
Else
error = #True
Break
EndIf
Next
ProcedureReturn error
EndProcedure
Procedure.i hrdLibrary(Library.s,*Init,Temp.i = #False,*Parameter = #Null)
Protected *hrd.HOT_RELOAD_DLL
If Library And *Init
If AddElement(hrd())
hrd()\name = Library
hrd()\copy = "hrd_" + Library
If Temp
hrd()\copy = GetTemporaryDirectory() + hrd()\copy
EndIf
hrd()\init = *Init
hrd()\parameter = *Parameter
*hrd = @hrd()
If hrdReload() = #Null
ProcedureReturn *hrd\handle
EndIf
EndIf
EndIf
ProcedureReturn #Null
EndProcedure
Procedure.i hrdFunction(Handle.i,Name.s)
Protected *name.Ascii
Protected *address
*name = Ascii(Name)
If *name
*address = GetProcAddress_(Handle,*name)
FreeMemory(*name)
EndIf
ProcedureReturn *address
EndProcedure
Code: Select all
EnableExplicit
XIncludeFile "hrd.pbi"
Global *hot;<- holds a function pointer (gets updated by the callback)
Procedure.i Init(*Name.String,Handle.i,*Parameter);<- callback used to update data/pointers
*hot = hrdFunction(Handle,"Dummy")
ProcedureReturn #Null
EndProcedure
Procedure.i Main()
hrdLibrary("hot.dll",@Init());<- example dll
If OpenWindow(0,#Null,#Null,200,100,#Null$,#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
ButtonGadget(1,20,30,160,30,"Test")
Repeat
If hrdReload();<- check if there where changes made to the library
Break
EndIf
Select WaitWindowEvent()
Case #PB_Event_Gadget
If EventGadget() = 1 And *hot
CallFunctionFast(*hot)
EndIf
Case #PB_Event_CloseWindow
Break
EndSelect
ForEver
CloseWindow(0)
EndIf
ProcedureReturn #Null
EndProcedure
End Main()
Code: Select all
EnableExplicit
ProcedureDLL.i Dummy()
MessageRequester("Message","Message :)")
ProcedureReturn #Null
EndProcedure