AutoHotkey.dll


AutoHotkey.dll is a custom build of AutoHotkey with some lowlevel functionality. It can be used in other programming languages and enables multithreading in AutoHotkey.
It was build by tinku99 and enhanced by HotKeyIt. GET THE PACKAGE HERE.

DllCall(A_DllPath "\" "desired function","???",...,"Cdecl ???")

Parameters

What do you need to use AutoHotkey.dll

You will need at minimum AutoHotkey.dll and AutoHotkey.exe or anther program able to load and run a dll.
AutoHotkey.dll is loaded into AutoHotkey.exe using handleLibrary:=DllCall("LoadLibrary","Str","dllpath or name"). Other languages that support loading a dll have similar functions.

Each additional loaded AutoHotkey.dll will serve an additional thread with full AutoHotkey functionality.

You can use DllCall("FreeLibrary","UInt",handleLibrary) to unload the dll.

Why do you need AutoHotkey.dll

Multithreading
By loading the dll (even the same (renamed) file ) we can run several threads simultaneously. For example you can use Input command to catch user input and perform your task in background so no Input gets lost.
It is even possible to use same variables using Alias() function, but be careful, when variable gets reallocated because its memory increases and you are accessing it, your program might crash, therefore you can use CriticalSection() to avoid simulations access.

Use AutoHotkey in other programming languages

You can also load the dll for example in phyton or another c++ program and use all AutoHotkey features.

Additional variables

A_DllPath will contain the corresponding thread file, so for AutoHotkey.exe it will be path of AutoHotkey.exe and for AutoHotkey.dll the path of used AutoHotkey.dll
A_ScriptOptions is an additional parameter passed when a thread is launched via ahkdll or ahktextdll.
A_AhkHwnd returns hwnd of main AutoHotkey window, useful for AutoHotkeyMini.dll due to lack of Gui commands.

Return Value

Each function has a different return value. See function its definition.

Remarks

When using Alias() to share a variables between threads, you should create your variable in an additional separate dll/thread, so you will have one thread that will manage your global variables. This seems to be necessary to prevent crash even when using CriticalSection, especially when using Objects with custom __Set, __Get and __Call functions.
All AutoHotkey.dll functions are case sensitive when using DllCall.
Remember to use #Persistent if you want to keep your thread alive.

Related

ahkdll, ahktextdll, ahkReady, addFile, addScript, ahkExec, ahkLabel, ahkFunction, ahkPostFunction, ahkassign, ahkgetvar, ahkTerminate, ahkReload, ahkFindFunc, ahkFindLabel, ahkPause, ahkExecuteLine, Alias, cacheEnable, FindFunc, getTokenValue, getVar, Static, AutoHotkeyMini, DynaCall, CriticalSection, MemoryLoadLibrary, ResourceLoadLibrary, MemoryGetProcAddress, MemoryFreeLibrary, Other Changes

Example

;AhkDllObject uses a file
obj:=AhkDllObject(A_ScriptDir . "\AutoHotkey.dll")
DynaCall(obj.ahktextdll,"&#Persistent`nMsgBox")
....

;AhkDllThread uses MemoryLoadLibrary (MultiThreading using one file only)
obj:=AhkDllThread(A_ScriptDir . "\AutoHotkey.dll")
DynaCall(obj.ahktextdll,"&#Persistent`nMsgBox")




AhkDllObject(dll=""){
    static
    static functions:="addFile|addScript|ahkExecuteLine|ahkFindFunc|ahkFindLabel|ahkFunction|ahkKey|ahkLabel|ahkPause|ahkPostFunction|ahkReady|ahkReload|ahkTerminate|ahkassign|ahkdll|ahkgetvar|ahktextdll"
    If !(dll){
        Loop % i
        {
            idx:=A_Index
            Loop,Parse,functions,|
            DynaCall(dll%idx% . "\" . A_LoopField)
            DllCall(dll%A_Index% . "\ahkTerminate")
            DllCall("FreeLibrary","UInt",dllmodule%A_Index%)
            obj%A_Index%=
            dll%A_Index%=
            dllmodule%A_Index%=
        }
        i=0
        return
    } else {
        Loop % i
        If (dll=dll%A_Index%)
        return obj%A_Index%
    }
    i++
    dllmodule%i%:=DllCall("LoadLibrary","str",dll)
    object := Object()
    object.ahkdll := DynaCall(dll . "\ahkdll","Str","","Str","","Str","","CDecl UInt")
    object.ahktextdll := DynaCall(dll . "\ahktextdll","Str","","Str","","Str","","CDecl UInt")
    object.ahkReady := DynaCall(dll . "\ahkReady","Cdecl Int")
    object.ahkReload := DynaCall(dll . "\ahkReload","Cdecl Int")
    object.ahkTerminate := DynaCall(dll . "\ahkTerminate","Int",0,"Cdecl Int")
    object.addFile := DynaCall(dll . "\addFile","Str","","uchar",0,"uchar",0,"CDecl UInt")
    object.addScript := DynaCall(dll . "\addScript","Str","","Int",0,"Int",0,"CDecl UInt")
    object.ahkassign := DynaCall(dll . "\ahkassign","Str","","Str","")
    object.ahkassign := DynaCall(dll . "\ahkgetvar","Str","","UInt","","Cdecl UInt")
    object.ahkExecuteLine := DynaCall(dll . "\ahkExecuteLine","UInt",0,"UInt",0,"UInt",0,"CDecl UInt")
    object.ahkFindFunc := DynaCall(dll . "\ahkFindFunc","Str","","CDecl UInt")
    object.ahkFindFunc := DynaCall(dll . "\ahkFindLabel","Str","","CDecl UInt")
    object.ahkFunction := DynaCall(dll . "\ahkFunction","Str","","Str","","Str","","Str","","Str","","Str","","Str","","Str","","Str","","Str","","CDecl Str")
    object.ahkPostFunction := DynaCall(dll . "\ahkPostFunction","Str","","Str","","Str","","Str","","Str","","Str","","Str","","Str","","Str","","Str","","CDecl Str")
    object.ahkgetvar := DynaCall(dll . "\ahkgetvar","Str","","UInt",0,"CDecl Str")
    object.ahkLabel := DynaCall(dll . "\ahkLabel","Str","","CDecl UInt")
    object.ahkPause := DynaCall(dll . "\ahkPause","Str","")
    object.ahkKey := DynaCall(dll . "\ahkPause","Str","")
    obj%i%:=object
    dll%i%:=dll
    return obj%i%
}






AhkDllThread(dll=""){
    static
    static functions:="ahkdll|ahktextdll|ahkReady|ahkReload|ahkTerminate|addFile|addScript|assign|ahkExecuteLine|ahkFindFunc|ahkFindLabel|ahkgetvar|ahkLabel|ahkPause"
    If !(dll){
        Loop % i
        {
            idx:=A_Index
            Loop,Parse,functions,|
            DynaCall(dll%idx% . "\" . A_LoopField)
            DllCall(dll%A_Index% . "\ahkTerminate")
            MemoryFreeLibrary(dllmodule%A_Index%)
            obj%A_Index%=
            dll%A_Index%=
            dllmodule%A_Index%=
        }
        i=0
        return
    } else {
        Loop % i
        If (dll=dll%A_Index%)
        return obj%A_Index%
    }
    i++
    dllmodule%i%:=MemoryLoadLibrary(dll)
    object := Object()
    Loop,Parse,functions,|
    object[A_LoopField]:=MemoryGetProcAddress(dllmodule%i%,A_LoopField)
    DynaCall(object.ahkdll,"Str","","Str","","Str","","CDecl UInt")
    DynaCall(object.ahktextdll,"Str","","Str","","Str","","CDecl UInt")
    DynaCall(object.ahkReady,"Cdecl Int")
    DynaCall(object.ahkReload,"Cdecl Int")
    DynaCall(object.ahkTerminate,"Int",0,"Cdecl Int")
    DynaCall(object.addFile,"Str","","uchar",0,"uchar",0,"CDecl UInt")
    DynaCall(object.addScript,"Str","","Int",0,"Int",0,"CDecl UInt")
    DynaCall(object.ahkassign,"Str","","Str","")
    DynaCall(object.ahkExecuteLine,"UInt",0,"UInt",0,"UInt",0,"CDecl UInt")
    DynaCall(object.ahkFindFunc,"Str","","CDecl UInt")
    DynaCall(object.ahkFunction,"Str","","Str","","Str","","Str","","Str","","Str","","Str","","Str","","Str","","Str","","CDecl Str")
    DynaCall(object.ahkPostFunction,"Str","","Str","","Str","","Str","","Str","","Str","","Str","","Str","","Str","","Str","","CDecl Str")
    DynaCall(object.ahkgetvar,"Str","","UInt",0,"CDecl Str")
    DynaCall(object.ahkLabel,"Str","","CDecl UInt")
    DynaCall(object.ahkPause,"Str","")
    obj%i%:=object
    dll%i%:=dll
    return obj%i%
}