Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

[AHK_H(+dll) / AHK_L / v2] AhkDllThread+AhkExported


  • Please log in to reply
274 replies to this topic
  • Guests
  • Last active:
  • Joined: --
No response to it yet? I use v1.1.07.01 Unicode x32. I used the AhkDllThread function of this page. <!-- m -->https://ahknet.autoh... ... Thread.ahk<!-- m --> I cannot tell whether I'm using the latest version of it since it doesn't have version information. Also I cannot find links to older versions of the function.

HotKeyIt
  • Moderators
  • 7439 posts
  • Last active: Jun 22 2016 09:14 PM
  • Joined: 18 Jun 2008
Works fine for me on XP SP3 :?

  • Guests
  • Last active:
  • Joined: --
With _L? I'm on Windows 7 64bit. Mind putting a link to the old versions?

HotKeyIt
  • Moderators
  • 7439 posts
  • Last active: Jun 22 2016 09:14 PM
  • Joined: 18 Jun 2008
If you are using _L it won't work from resource, _L is not able to load dll from Memory itself so it needs AutoHotkey.dll to do that, even compiled.

So you have to use the AutoHotkeySC.bin from AutoHotkey_H package to be able to load dll from Resource.

You can try to implemnt _MemoryLibrary in AhkDllThread(), then you could load the dll from Memory also in AHK_L.

  • Guests
  • Last active:
  • Joined: --
I remember it used to work with _L though. I'd like to test with older versions but where can I find them?

  • Guests
  • Last active:
  • Joined: --

You can try to implemnt _MemoryLibrary in AhkDllThread(), then you could load the dll from Memory also in AHK_L.

How hard for you to implement it in AhkDllThread()?

  • Guests
  • Last active:
  • Joined: --
This works with a compiled _L script, loading dll from resource.
#include <_MemoryLibrary> 
If !A_IsCompiled {
	msgbox this script is for a compiled script 
	exitapp
}

LoadScriptResource(Data, ".\AutoHotkey.dll")
MemLib := new _MemoryLibrary(&data)
NewMemLib := new _MemoryLibrary(&data)

DllCall(MemLib.GetProcAddress("ahktextdll"),"Str","MsgBox Hello from Thread","Str","","Str","") ; start first AutoHotkey.dll thread
DllCall(NewMemLib.GetProcAddress("ahktextdll"),"Str","MsgBox Hello from other Thread","Str","","Str","") ; start another AutoHotkey.dll thread
Sleep 1000
MsgBox AutoHotkey.dll started, press OK to terminate.
DllCall(MemLib.GetProcAddress("ahkterminate")),        MemLib.Free()
DllCall(NewMemLib.GetProcAddress("ahkterminate")),      NewMemLib.Free()
MsgBox AutoHotkey.dll threads terminated and memory freed

Return

FileInstall, .\AutoHotkey.dll, -	;never executed

LoadScriptResource(ByRef Data,Name, Type = 10)
{
    lib := DllCall("GetModuleHandle", "ptr", 0, "ptr")
    res := DllCall("FindResource", "ptr", lib, "str", Name, "ptr", Type, "ptr")
    DataSize := DllCall("SizeofResource", "ptr", lib, "ptr", res, "uint")
    hresdata := DllCall("LoadResource", "ptr", lib, "ptr", res, "ptr")
    VarSetCapacity(Data,DataSize)
    DllCall("RtlMoveMemory","PTR",&Data,"PTR",DllCall("LockResource", "ptr", hresdata, "ptr"),"UInt",DataSize)
    DllCall("FreeResource","PTR",hresdata)
    return DataSize
}
I wonder why HotKeyIt seems to be reluctant to implement it in the AhkDllThread() function.

HotKeyIt
  • Moderators
  • 7439 posts
  • Last active: Jun 22 2016 09:14 PM
  • Joined: 18 Jun 2008
Can you try this :?:
#include <FileGetVersionInfo>

#include <_MemoryLibrary>

AhkDllThread(dll="AutoHotkey.dll",obj=0){

	static init,ahkfunction,hLib,ahkexec,DynaCall:="DynaCall", MemoryLoadLibrary:="MemoryLoadLibrary",MemoryFreeLibrary:="MemoryFreeLibrary"

			,ResourceLoadLibrary:="ResourceLoadLibrary", MemoryGetProcAddress:="MemoryGetProcAddress"

	static AHK_H:=FileGetVersionInfo_AW(A_AhkPath,"InternalName")="AutoHotkey_H"

	static base:={__Delete:"AhkDllThread"}

	static functions ="

(Join

ahkFunction:s=sssssssssss|ahkPostFunction:i=sssssssssss|

ahkdll:ut=sss|ahktextdll:ut=sss|ahkReady:|ahkReload:ui=|

ahkTerminate:i|addFile:ut=sucuc|addScript:ut=si|ahkExec:ui=s|

ahkassign:ui=ss|ahkExecuteLine:ut=utuiui|ahkFindFunc:ut=s|

ahkFindLabel:ut=s|ahkgetvar:s=sui|ahkLabel:ui=sui|ahkPause:s

)"

	static AhkDllThreadfunc ="

(Join`r`n

#Persistent

#NoTrayIcon

Return

AhkDllThread(dll=""AutoHotkey.dll"",obj=0,map=""""){

	static functions = ""ahkFunction:s=sssssssssss|ahkPostFunction:i=sssssssssss|""

							. ""ahkdll:ut=sss|ahktextdll:ut=sss|ahkReady:|ahkReload:ui=|""

							. ""ahkTerminate:i|addFile:ut=sucuc|addScript:ut=si|ahkExec:ui=s|""

							. ""ahkassign:ui=ss|ahkExecuteLine:ut=utuiui|ahkFindFunc:ui=s|""

							. ""ahkFindLabel:ui=s|ahkgetvar:s=sui|ahkLabel:ui=sui|ahkPause:s""

	If (dll=""0"")

		return object:=""""

	else If (!FileExist(dll)){

		MsgBox File: `%dll`% does not exist`, provide correct path for AutoHotkey.dll

		ExitApp

	}

	object:=IsObject(obj)?obj:{},object[""""]:= MemoryLoadLibrary(dll)

	Loop,Parse,functions,|

	{

		StringSplit,v,A_LoopField,:

		object[map="""" ? v1 ]:=DynaCall(MemoryGetProcAddress(object[""""],v1),v2)

	}

	object.base:=Object(" (&base) ")

	return &object

}

)"

	If IsObject(dll){

		dll.ahkterminate()

		If !AHK_H{

			DllCall(ahkExec,"Str","MemoryFreeLibrary(" dll[""] ")")

		} else %MemoryFreeLibrary%(dll[""])

		return

	} else if (!FileExist(dll) && !A_IsCompiled){

		MsgBox File: %dll%`ndoes not exist`, provide correct path for AutoHotkey.dll

		ExitApp

	}

	If !AHK_H{

		If (init || ((hLib:=new _MemoryLibrary(A_IsCompiled?DllCall("LockResource","ptr",DllCall("LoadResource","ptr",lib,"ptr",DllCall("FindResource","ptr",lib:=DllCall("GetModuleHandle","ptr",0,"ptr"),"str",dll,"ptr",10,"ptr"),"ptr"),"ptr"):dll)) && (Init:=hLib.GetProcAddress("ahktextdll")))){

			If (ahkfunction || (DllCall(init,"Str",AhkDllThreadfunc,"Str","","Str","","Cdecl UInt") && (ahkfunction:=hLib.GetProcAddress("ahkFunction")) && (ahkExec:=hLib.GetProcAddress("ahkExec")))){

				return Object(0+DllCall(ahkfunction,"Str","AhkDllThread","Str",dll,"Str","","Str","","Str","","Str","","Str","","Str","","Str","","Str","","Str","","CDecl Str"))

				;reset internal return memory in autoHotkey.dll and release object

				,DllCall(ahkfunction,"Str","AhkDllThread","Str","0","Str","","Str","","Str","","Str","","Str","","Str","","Str","","Str","","Str","","CDecl Str")

			} else {

				MsgBox Could not load script in %dll%

				Return 0

			}

		} else {

			MsgBox Could not load %dll%

			Return 0

		}

	}

	object:=IsObject(obj)?obj:{},object[""]:= A_IsCompiled ? %ResourceLoadLibrary%(dll) : %MemoryLoadLibrary%(dll)

	Loop,Parse,functions,|

	{

		StringSplit,v,A_LoopField,:

		object[map="" ? v1 ]:=%DynaCall%(%MemoryGetProcAddress%(object[""],v1),v2)

	}

	return object,object.base:=base

}


  • Guests
  • Last active:
  • Joined: --
Doesn't seem to work with a compiled script of _L. :? May RtlMoveMemory be required?

HotKeyIt
  • Moderators
  • 7439 posts
  • Last active: Jun 22 2016 09:14 PM
  • Joined: 18 Jun 2008
What is the error you get? Have you got the latest Unicode 32-bit.bin?
Can you check if you get a pointer in compiled script:
MsgBox % DllCall("LockResource","ptr",DllCall("LoadResource","ptr",lib,"ptr",DllCall("FindResource","ptr",lib:=DllCall("GetModuleHandle","ptr",0,"ptr"),"str",[color=red]".\AutoHotkey.dll"[/color],"ptr",10,"ptr"),"ptr"),"ptr")
This is the code I have compiled, works on XP SP3.
If 0
	FileInstall,.\AutoHotkey.dll,-
dll:=AhkDllThread(".\AutoHotkey.dll")
dll.ahktextdll("MsgBox from Thread")
MSgBox end


#include <FileGetVersionInfo>
#include <_MemoryLibrary>
AhkDllThread(dll="AutoHotkey.dll",obj=0){
	static init,ahkfunction,hLib,ahkexec,DynaCall:="DynaCall", MemoryLoadLibrary:="MemoryLoadLibrary",MemoryFreeLibrary:="MemoryFreeLibrary"
			,ResourceLoadLibrary:="ResourceLoadLibrary", MemoryGetProcAddress:="MemoryGetProcAddress"
	static AHK_H:=FileGetVersionInfo_AW(A_AhkPath,"InternalName")="AutoHotkey_H"
	static base:={__Delete:"AhkDllThread"}
	static functions ="
(Join
ahkFunction:s=sssssssssss|ahkPostFunction:i=sssssssssss|
ahkdll:ut=sss|ahktextdll:ut=sss|ahkReady:|ahkReload:ui=|
ahkTerminate:i|addFile:ut=sucuc|addScript:ut=si|ahkExec:ui=s|
ahkassign:ui=ss|ahkExecuteLine:ut=utuiui|ahkFindFunc:ut=s|
ahkFindLabel:ut=s|ahkgetvar:s=sui|ahkLabel:ui=sui|ahkPause:s
)"
	static AhkDllThreadfunc ="
(Join`r`n
#Persistent
#NoTrayIcon
Return
AhkDllThread(dll=""AutoHotkey.dll"",obj=0,map=""""){
	static functions = ""ahkFunction:s=sssssssssss|ahkPostFunction:i=sssssssssss|""
							. ""ahkdll:ut=sss|ahktextdll:ut=sss|ahkReady:|ahkReload:ui=|""
							. ""ahkTerminate:i|addFile:ut=sucuc|addScript:ut=si|ahkExec:ui=s|""
							. ""ahkassign:ui=ss|ahkExecuteLine:ut=utuiui|ahkFindFunc:ui=s|""
							. ""ahkFindLabel:ui=s|ahkgetvar:s=sui|ahkLabel:ui=sui|ahkPause:s""
	If (dll=""0"")
		return object:=""""
	else If (!FileExist(dll)){
		MsgBox File: `%dll`% does not exist`, provide correct path for AutoHotkey.dll
		ExitApp
	}
	object:=IsObject(obj)?obj:{},object[""""]:= MemoryLoadLibrary(dll)
	Loop,Parse,functions,|
	{
		StringSplit,v,A_LoopField,:
		object[map="""" ? v1 ]:=DynaCall(MemoryGetProcAddress(object[""""],v1),v2)
	}
	object.base:=Object(" (&base) ")
	return &object
}
)"
	If IsObject(dll){
		dll.ahkterminate()
		If !AHK_H{
			DllCall(ahkExec,"Str","MemoryFreeLibrary(" dll[""] ")")
		} else %MemoryFreeLibrary%(dll[""])
		return
	} else if (!FileExist(dll) && !A_IsCompiled){
		MsgBox File: %dll%`ndoes not exist`, provide correct path for AutoHotkey.dll
		ExitApp
	}
	If !AHK_H{
		If (init || ((hLib:=new _MemoryLibrary(A_IsCompiled?DllCall("LockResource","ptr",DllCall("LoadResource","ptr",lib,"ptr",DllCall("FindResource","ptr",lib:=DllCall("GetModuleHandle","ptr",0,"ptr"),"str",dll,"ptr",10,"ptr"),"ptr"),"ptr"):dll)) && (Init:=hLib.GetProcAddress("ahktextdll")))){
			If (ahkfunction || (DllCall(init,"Str",AhkDllThreadfunc,"Str","","Str","","Cdecl UInt") && (ahkfunction:=hLib.GetProcAddress("ahkFunction")) && (ahkExec:=hLib.GetProcAddress("ahkExec")))){
				return Object(0+DllCall(ahkfunction,"Str","AhkDllThread","Str",dll,"Str","","Str","","Str","","Str","","Str","","Str","","Str","","Str","","Str","","CDecl Str"))
				;reset internal return memory in autoHotkey.dll and release object
				,DllCall(ahkfunction,"Str","AhkDllThread","Str","0","Str","","Str","","Str","","Str","","Str","","Str","","Str","","Str","","Str","","CDecl Str")
			} else {
				MsgBox Could not load script in %dll%
				Return 0
			}
		} else {
			MsgBox Could not load %dll%
			Return 0
		}
	}
	object:=IsObject(obj)?obj:{},object[""]:= A_IsCompiled ? %ResourceLoadLibrary%(dll) : %MemoryLoadLibrary%(dll)
	Loop,Parse,functions,|
	{
		StringSplit,v,A_LoopField,:
		object[map="" ? v1 ]:=%DynaCall%(%MemoryGetProcAddress%(object[""],v1),v2)
	}
	return object,object.base:=base
}


  • Guests
  • Last active:
  • Joined: --

Have you got the latest Unicode 32-bit.bin?

Yes.
MsgBox % DllCall("LockResource","ptr",DllCall("LoadResource","ptr",lib,"ptr",DllCall("FindResource","ptr",lib:=DllCall("GetModuleHandle","ptr",0,"ptr"),"str",".\AutoHotkey.dll","ptr",10,"ptr"),"ptr"),"ptr")
return
FileInstall, .\AutoHotkey.dll, -
I get:

5036884

Looks like a memory address so it should be okey.

The error I get from the second script in your above post is:

File: .\AutoHotkey.dll does not exist, provide correct path for AutoHotkey.dll

This means it tries to load from file not resource.

HotKeyIt
  • Moderators
  • 7439 posts
  • Last active: Jun 22 2016 09:14 PM
  • Joined: 18 Jun 2008
Next one, please try :)
#include <FileGetVersionInfo>

#include <_MemoryLibrary>

AhkDllThread_LoadScriptResource(){

    lib := DllCall("GetModuleHandle", "ptr", 0, "ptr")

	If !(res := DllCall("FindResource", "ptr", lib, "str", ">AUTOHOTKEY SCRIPT<", "ptr", 10, "ptr"))

		res := DllCall("FindResource", "ptr", lib, "str", ">AHK WITH ICON<", "ptr", 10, "ptr")

    DataSize := DllCall("SizeofResource", "ptr", lib, "ptr", res, "uint")

    hresdata := DllCall("LoadResource", "ptr", lib, "ptr", res, "ptr")

	Return DATA:=StrGet(DllCall("LockResource", "ptr", hresdata, "ptr"),DataSize,"UTF-8")

} 

AhkDllThread(dll="AutoHotkey.dll",obj=0){

	static init,ahkfunction,hLib,dllptr,libScript,ahkexec,DynaCall:="DynaCall", MemoryLoadLibrary:="MemoryLoadLibrary",MemoryFreeLibrary:="MemoryFreeLibrary"

			,ResourceLoadLibrary:="ResourceLoadLibrary", MemoryGetProcAddress:="MemoryGetProcAddress"

	static AHK_H:=FileGetVersionInfo_AW(A_AhkPath,"InternalName")="AutoHotkey_H"

	static base:={__Delete:"AhkDllThread"}

	static functions ="

(Join

ahkFunction:s=sssssssssss|ahkPostFunction:i=sssssssssss|

ahkdll:ut=sss|ahktextdll:ut=sss|ahkReady:|ahkReload:ui=|

ahkTerminate:i|addFile:ut=sucuc|addScript:ut=si|ahkExec:ui=s|

ahkassign:ui=ss|ahkExecuteLine:ut=utuiui|ahkFindFunc:ut=s|

ahkFindLabel:ut=s|ahkgetvar:s=sui|ahkLabel:ui=sui|ahkPause:s

)"

	static AhkDllThreadfunc ="

(Join`r`n

#Persistent

#NoTrayIcon

Return

AhkDllThreadDLL(dll=""AutoHotkey.dll"",obj=0){

	static functions = ""ahkFunction:s=sssssssssss|ahkPostFunction:i=sssssssssss|""

							. ""ahkdll:ut=sss|ahktextdll:ut=sss|ahkReady:|ahkReload:ui=|""

							. ""ahkTerminate:i|addFile:ut=sucuc|addScript:ut=si|ahkExec:ui=s|""

							. ""ahkassign:ui=ss|ahkExecuteLine:ut=utuiui|ahkFindFunc:ui=s|""

							. ""ahkFindLabel:ui=s|ahkgetvar:s=sui|ahkLabel:ui=sui|ahkPause:s""

	If (dll=""0"")

		return object:=""""

	else If (!FileExist(dll) && obj=0){

		MsgBox File: `%dll`% does not exist`, provide correct path for AutoHotkey.dll

		ExitApp

	}

	object:=[]

	object[""""] := new _MemoryLibrary(obj?obj:dll)

	Loop,Parse,functions,|

	{

		StringSplit,v,A_LoopField,:

		object[map="""" ? v1 ]:=DynaCall(object[""""].GetProcAddress(v1),v2)

	}

	object.base:=Object(" (&base) ")

	return &object

}

)"

	If IsObject(dll){

		dll.ahkterminate()

		If !AHK_H{

			dll[""].Free()

		} else %MemoryFreeLibrary%(dll[""])

		return

	} else if (!FileExist(dll) && !A_IsCompiled){

		MsgBox File: %dll%`ndoes not exist`, provide correct path for AutoHotkey.dll

		ExitApp

	}

	If !AHK_H{

		If (init || ((hLib:=new _MemoryLibrary(A_IsCompiled?(dllptr:=DllCall("LockResource","ptr",DllCall("LoadResource","ptr",lib,"ptr",DllCall("FindResource","ptr",lib:=DllCall("GetModuleHandle","ptr",0,"ptr"),"str",dll,"ptr",10,"ptr"),"ptr"),"ptr")):dll)) && (Init:=hLib.GetProcAddress("ahktextdll")) && (LibScript:=AhkDllThread_LoadScriptResource()))){

			If (ahkfunction || (DllCall(init,"Str",AhkDllThreadfunc "`n" LibScript,"Str","","Str","","Cdecl UInt") && (ahkfunction:=hLib.GetProcAddress("ahkFunction")) && (ahkExec:=hLib.GetProcAddress("ahkExec")))){

				return Object(0+DllCall(ahkfunction,"Str","AhkDllThreadDLL","Str",dll,"Str",dllptr,"Str","","Str","","Str","","Str","","Str","","Str","","Str","","Str","","CDecl Str"))

				;reset internal return memory in autoHotkey.dll and release object

				,DllCall(ahkfunction,"Str","AhkDllThreadDLL","Str","0","Str","","Str","","Str","","Str","","Str","","Str","","Str","","Str","","Str","","CDecl Str")

			} else {

				MsgBox Could not load script in %dll%

				Return 0

			}

		} else {

			MsgBox Could not load %dll%

			Return 0

		}

	}

	object:=IsObject(obj)?obj:{},object[""]:= A_IsCompiled ? %ResourceLoadLibrary%(dll) : %MemoryLoadLibrary%(dll)

	Loop,Parse,functions,|

	{

		StringSplit,v,A_LoopField,:

		object[map="" ? v1 ]:=%DynaCall%(%MemoryGetProcAddress%(object[""],v1),v2)

	}

	return object,object.base:=base

}


  • Guests
  • Last active:
  • Joined: --
Thanks, it loads dll from resource with _L but a few issues remain. First, it's extremely slow. Second, the memory don't get freed after releasing the thread objects.

This code is from the thread in Ask For Help.
#Noenv
SetWorkingDir %A_ScriptDir%
#persistent
#include <AhkDllThread>
oThreads := []   

If 0 {
    FileInstall, .\AutoHotkey32.dll,- ; never runs.
}
if !FileExist(strDllLocation := A_IsCompiled ? ".\AutoHotkey32.dll" : A_PtrSize = 8 ? A_ScriptDir "\AutoHotkey64.dll" : A_ScriptDir "\AutoHotkey32.dll") {
   msgbox The autohotkey.dll is not found.
   ExitApp
}
loop 15
{
   oThreads[A_Index]:=AhkDllThread(strDllLocation)
   oThreads[A_Index].ahktextdll("
   (Ltrim
      #NoTrayIcon
      msgbox " A_Index "
      ExitApp
   )")
}
Process, Exist
MsgBox Check memory of PID %ErrorLevel% now, click OK to unload dlls.
While % oThreads.MaxIndex() ; Can be Loop 15 as well
   oThreads.Remove() ; Thread will be terminated internally as well 
MsgBox Memory freed.


HotKeyIt
  • Moderators
  • 7439 posts
  • Last active: Jun 22 2016 09:14 PM
  • Joined: 18 Jun 2008
Thanks that should be better now, though it is still slower and not so much memory is released (but I think it will once OS will request it or EmptyMem() is executed)

#include <FileGetVersionInfo>
#include <_MemoryLibrary>
AhkDllThread_LoadScriptResource(){
    lib := DllCall("GetModuleHandle", "ptr", 0, "ptr")
	If !(res := DllCall("FindResource", "ptr", lib, "str", ">AUTOHOTKEY SCRIPT<", "ptr", 10, "ptr"))
		res := DllCall("FindResource", "ptr", lib, "str", ">AHK WITH ICON<", "ptr", 10, "ptr")
    DataSize := DllCall("SizeofResource", "ptr", lib, "ptr", res, "uint")
    hresdata := DllCall("LoadResource", "ptr", lib, "ptr", res, "ptr")
	Return DATA:=StrGet(DllCall("LockResource", "ptr", hresdata, "ptr"),DataSize,"UTF-8")
} 
AhkDllThread(dll="AutoHotkey.dll",obj=0){
	static init,ahkfunction,hLib,dllptr,libScript,ahkexec,DynaCall:="DynaCall", MemoryLoadLibrary:="MemoryLoadLibrary",MemoryFreeLibrary:="MemoryFreeLibrary"
			,ResourceLoadLibrary:="ResourceLoadLibrary", MemoryGetProcAddress:="MemoryGetProcAddress"
	static AHK_H:=FileGetVersionInfo_AW(A_AhkPath,"InternalName")="AutoHotkey_H"
	static base:={__Delete:"AhkDllThread"}
	static functions ="
(Join
ahkFunction:s=sssssssssss|ahkPostFunction:i=sssssssssss|
ahkdll:ut=sss|ahktextdll:ut=sss|ahkReady:|ahkReload:ui=|
ahkTerminate:i|addFile:ut=sucuc|addScript:ut=si|ahkExec:ui=s|
ahkassign:ui=ss|ahkExecuteLine:ut=utuiui|ahkFindFunc:ut=s|
ahkFindLabel:ut=s|ahkgetvar:s=sui|ahkLabel:ui=sui|ahkPause:s
)"
	static AhkDllThreadfunc ="
(Join`r`n
#Persistent
SetBatchLines,-1
#NoTrayIcon
Return
AhkDllThreadDLL(dll=""AutoHotkey.dll"",obj=0){
	static functions = ""ahkFunction:s=sssssssssss|ahkPostFunction:i=sssssssssss|""
							. ""ahkdll:ut=sss|ahktextdll:ut=sss|ahkReady:|ahkReload:ui=|""
							. ""ahkTerminate:i|addFile:ut=sucuc|addScript:ut=si|ahkExec:ui=s|""
							. ""ahkassign:ui=ss|ahkExecuteLine:ut=utuiui|ahkFindFunc:ui=s|""
							. ""ahkFindLabel:ui=s|ahkgetvar:s=sui|ahkLabel:ui=sui|ahkPause:s""
	If (dll=""0"")
		return object:=""""
	else If (!FileExist(dll) && obj=0){
		MsgBox File: `%dll`% does not exist`, provide correct path for AutoHotkey.dll
		ExitApp
	}
	object:=[]
	object[""""] := new _MemoryLibrary(obj?obj:dll)
	Loop,Parse,functions,|
	{
		StringSplit,v,A_LoopField,:
		object[map="""" ? v1 ]:=DynaCall(object[""""].GetProcAddress(v1),v2)
	}
	object.base:=Object(" (&base) ")
	return &object
}
)"
	If IsObject(dll){
		dll.ahkterminate()
		If !AHK_H {
			dll.Free()
		} else %MemoryFreeLibrary%(dll[""])
		return
	} else if (!FileExist(dll) && !A_IsCompiled){
		MsgBox File: %dll%`ndoes not exist`, provide correct path for AutoHotkey.dll
		ExitApp
	}
	If !AHK_H{
		If (init || ((hLib:=new _MemoryLibrary(A_IsCompiled?(dllptr:=DllCall("LockResource","ptr",DllCall("LoadResource","ptr",lib,"ptr",DllCall("FindResource","ptr",lib:=DllCall("GetModuleHandle","ptr",0,"ptr"),"str",dll,"ptr",10,"ptr"),"ptr"),"ptr")):dll)) && (Init:=hLib.GetProcAddress("ahktextdll")) && (LibScript:=AhkDllThread_LoadScriptResource()))){
			If (ahkfunction || (DllCall(init,"Str",AhkDllThreadfunc "`n" LibScript,"Str","","Str","","Cdecl UInt") && (ahkfunction:=hLib.GetProcAddress("ahkFunction")) && (ahkExec:=hLib.GetProcAddress("ahkExec")))){
				return Object(0+DllCall(ahkfunction,"Str","AhkDllThreadDLL","Str",dll,"Str",dllptr,"Str","","Str","","Str","","Str","","Str","","Str","","Str","","Str","","CDecl Str"))
				;reset internal return memory in autoHotkey.dll and release object
				,DllCall(ahkfunction,"Str","AhkDllThreadDLL","Str","0","Str","","Str","","Str","","Str","","Str","","Str","","Str","","Str","","Str","","CDecl Str")
			} else {
				MsgBox Could not load script in %dll%
				Return 0
			}
		} else {
			MsgBox Could not load %dll%
			Return 0
		}
	}
	object:=IsObject(obj)?obj:{},object[""]:= A_IsCompiled ? %ResourceLoadLibrary%(dll) : %MemoryLoadLibrary%(dll)
	Loop,Parse,functions,|
	{
		StringSplit,v,A_LoopField,:
		object[map="" ? v1 ]:=%DynaCall%(%MemoryGetProcAddress%(object[""],v1),v2)
	}
	return object,object.base:=base
}


  • Guests
  • Last active:
  • Joined: --
The speed seems to became acceptable although I still feel it is slow. One new issue arose that now the non-compiled script causes the error saying, Could not load <the dll path>.

Thanks that should be better now, though it is still slower and not so much memory is released (but I think it will once OS will request it or EmptyMem() is executed)

I really wish the memory gets released with the destructor. I'd like to know why creating a thread increases the memory usage of the script. I suppose it's because it copies the dll binary data into a variable. If so, simply clearing the variable should do the job, shouldn't it? I could not find which variable contains it though, reading your code.

By the way, the sample test code in my previous post had a minor issue. So here is the update.
#Noenv
SetWorkingDir %A_ScriptDir%
#persistent
#include <AhkDllThread>
oThreads := []   

If 0 {
    FileInstall, .\AutoHotkey32.dll,- ; for compiling with Unicode 32-bit.bin
}
strDllLocation := A_IsCompiled ? ".\AutoHotkey32.dll" : A_PtrSize = 8 ? A_ScriptDir "\AutoHotkey64.dll" : A_ScriptDir "\AutoHotkey32.dll"
if !A_IsCompiled && !FileExist(strDllLocation) {
   msgbox The autohotkey.dll is not found.
   ExitApp
}
loop 15
{
   oThreads[A_Index]:=AhkDllThread(strDllLocation)
   oThreads[A_Index].ahktextdll("
   (Ltrim
      #NoTrayIcon
      msgbox " A_Index "
      ExitApp
   )")
}
Process, Exist
MsgBox Check memory of PID %ErrorLevel% now, click OK to unload dlls.
While % oThreads.MaxIndex() ; Can be Loop 15 as well
   oThreads.Remove() ; Thread will be terminated internally as well 
MsgBox Memory freed.

Also I have a suggestion to check if the static variables exist so that it can avoid calling the class or function multiple times. I'm not sure if it creates another issue.
If (init || ((hLib ? hLib : hLib:=new _MemoryLibrary(A_IsCompiled?(dllptr ? dllptr : dllptr:=DllCall("LockResource","ptr",DllCall("LoadResource","ptr",lib,"ptr",DllCall("FindResource","ptr",lib ? lib : lib:=DllCall("GetModuleHandle","ptr",0,"ptr"),"str",dll,"ptr",10,"ptr"),"ptr"),"ptr")):dll)) && (Init:=hLib.GetProcAddress("ahktextdll")) && (LibScript ? LibScript : LibScript:=AhkDllThread_LoadScriptResource()))){