Jump to content

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

AutoHotkey.dll


  • Please log in to reply
1328 replies to this topic
HotKeyIt
  • Moderators
  • 7439 posts
  • Last active: Jun 22 2016 09:14 PM
  • Joined: 18 Jun 2008

1. I try to reproduce and have a look but it might be a windows feature or bug and I am not sure if we can do anything about it.

2. This happens when memory is corrupted or misused, windows feature.

3. On my to do list.



Larctic
  • Members
  • 303 posts
  • Last active: May 10 2016 04:56 PM
  • Joined: 21 Jul 2012

BUG Report:
Use addScript add code, if the code contains "#if", can not properly get GetKeyState ()

DLL:=AhkDllThread()

m=
( % `
f1::
if !IsLabel("a")
h_Self.addScript("a:`nMsgBox % GetKeyState(""f1"", ""P"")`nReturn`n#if AAA`nw::`n#if",0)
Gosub % "a"
)

DLL.ahktextdll("global h_Self:=Object(" Object(DLL) ")`n" m) 


MsgBox  Press "F1" `nThe first Back to Results : 0`nThe second  Back to Results : 1


HotKeyIt
  • Moderators
  • 7439 posts
  • Last active: Jun 22 2016 09:14 PM
  • Joined: 18 Jun 2008

This is because Keyboard hook needs to be installed upfront to allow it to detect the state of key before hotkey is pressed.

m=
( % `
#InstallKeybdHook
f1::
...


RHCP
  • Members
  • 1228 posts
  • Last active: Apr 08 2017 06:17 PM
  • Joined: 29 May 2006

What is the correct method for clearing the contents of a criticalObject and then inserting new values into it.

For example, would this replace the the criticalObject with a reference/ptr to gatheredData?

gatheredData := ["a", "b", "c"]
criticalObject := gatheredData

Can you use clone? Or would this replace criticalObject with an normal AHK object?

gatheredData := ["a", "b", "c"]
criticalObject := gatheredData.clone()

Or should I clear the criticalObject data and then manually add the info?

gatheredData := ["a", "b", "c"]
criticalObject := []
for k, v in gatheredData
	criticalObject[k] := v

Thanks.



HotKeyIt
  • Moderators
  • 7439 posts
  • Last active: Jun 22 2016 09:14 PM
  • Joined: 18 Jun 2008

When you do criticalobject:=[], you delete the criticalobject and assign normal object to it. Note that CriticalSection will not be deleted automatically.

You have to create a new CriticalObject, following example requires v2 due to Type().

gatheredData := ["d", "e", "f"]
obj:=CriticalObject(["a","b","c"])
MsgBox % Type(obj)
DllCall("DeleteCriticalSection","PTR",CriticalObject(obj,2))
obj:=CriticalObject(gatheredData)
MsgBox % Type(obj)


RHCP
  • Members
  • 1228 posts
  • Last active: Apr 08 2017 06:17 PM
  • Joined: 29 May 2006

Sorry I didn't explain that well. And I'm a bit of an idiot. I'm so used to 'clearing' an object by doing := [], I didn't think to just call obj.remove(key) on all of the keys inside the object.

 

I basically want to create a critical object, pass it to a worker thread which will update it with new contents every few hundred ms. Other threads in the script will then use this data to do stuff. 

 

Basically something like this.

Spoiler

 

Is it safe to read the contents keys/values of an object from multiple threads at once without locking the critical section? If so, I  assume it would be more efficient to just use a normal (non-thread safe) object and pass a critical section to the threads. That way the objects associated critical section will only be locked by the data gathering thread when it is actually writing data to the object and when the other threads are simply reading this data they wont lock each other out.

 

The other more important benefit is that it would prevent any of the threads reading the objects data before it has been fully updated with all of the new items.

 

Thanks again.



HotKeyIt
  • Moderators
  • 7439 posts
  • Last active: Jun 22 2016 09:14 PM
  • Joined: 18 Jun 2008

You can read and write data from/to the CriticalSection at the same time from multiple threads.

The first thread will lock access to the object so every other tread trying to access the object will automatically wait.

 

When you don't want other threads to access your object before you fully updated it, I would suggest using CriticalSection + normal object.

; Constantly loop through and gather/update data on items
script = 
( C %
   CriSec=%1%
   obj=%2%
   obj:=Object(obj+0)
	loop 
	{ 	
		; gather some data
		tmp := []
		random, count, 2, 10
		loop, % count
		{
			Random, item, 0, 100
			tmp[item] := "some other values which change, but are specific to this item"
		}
		; Remove any keys which no longer exist in the gathered data
        Lock(CriSec)
		for k in critObj
		{ 
			if !tmp.hasKey(k)
               obj.remove(k, "")
		}
		; Update the old information with new items and new values for existing items
		for k, v in tmp 
			obj[k] := v
         UnLock(CriSec)
		sleep 200 ; Actually the thread will be doing other stuff 
	}
)
obj := []
CriSec:=CriticalSection()
workerThread := AhkDllThread(A_AhkDir() "\AutoHotkey.dll") ;"Included Files\ahkH\AutoHotkeyMini.dll")
workerThread.ahktextdll(script,,CriSec " " &obj)
return 

f1::
; Use the gathered data for stuff in other threads
Lock(CriSec)
objtree(obj)  ; Single best AHK function ever written! :)
UnLock(CriSec)
return 


alvitawa
  • Members
  • 98 posts
  • Last active: Oct 14 2017 02:16 PM
  • Joined: 07 Feb 2013

Does somebody have typedefs for c++ to define all the functions? I mean these:

 

typedef UINT(*pahkdll)(LPTSTR script, LPTSTR p1, LPTSTR p2);
typedef UINT(*pahktextdll)(LPTSTR script, LPTSTR p1, LPTSTR p2);
typedef BOOL (*pahkExec)(LPTSTR script);
typedef UINT(*pahkFunction)(LPTSTR function, LPTSTR pars);
typedef BOOL(*pahkReady)(void);
 
the above work but I cant figure out what the return types must be for other functions(for example addFile, it returns a pointer but I dont know what kind of pointer)


HotKeyIt
  • Moderators
  • 7439 posts
  • Last active: Jun 22 2016 09:14 PM
  • Joined: 18 Jun 2008

You can find all details in source: https://github.com/H...ource/exports.h

addFile and addScript return a pointer to the first newly created line.



alvitawa
  • Members
  • 98 posts
  • Last active: Oct 14 2017 02:16 PM
  • Joined: 07 Feb 2013

Ah thank you! I knew they returned "a pointer to the first newly created line" but I can't write that on c++ :), thanks that source was exactly what I meant.



alvitawa
  • Members
  • 98 posts
  • Last active: Oct 14 2017 02:16 PM
  • Joined: 07 Feb 2013

I get this error a lot when interacting with autohotkey.dll do you know what I could do to solve it?

An unhandled exception of type 'System.AccessViolationException' occurred in Project.exe


Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

For example when I do this:

typedef int(*tcoolfunc)();

tcoolfunc function = (tcoolfunc)dll.ahkFindFunc((wchar_t*)L"coolfunc");
function(); //<--Here comes the error

ahkFindFunc is defined so:

typedef UINT_PTR(*pahkFindFunc)(LPTSTR funcname);


pahkFindFunc ahkFindFunc;


ahkFindFunc = (pahkFindFunc)GetProcAddress(hInstLibrary, "ahkFindFunc");

I also got it when I wanted to define all of the callable functions of the dll:

	typedef int(*pahkPause)(LPTSTR aChangeTo);
	typedef UINT_PTR(*pahkFindLabel)(LPTSTR aLabelName);
	typedef LPTSTR(*pahkgetvar)(LPTSTR name, unsigned int getVar);
	typedef int(*pahkassign)(LPTSTR name, LPTSTR value);
	typedef UINT_PTR(*pahkExecuteLine)(UINT_PTR line, unsigned int aMode, unsigned int wait);
	typedef int(*pahkLabel)(LPTSTR aLabelName, unsigned int nowait);
	typedef UINT_PTR(*pahkFindFunc)(LPTSTR funcname);
	typedef LPTSTR(*pahkFunction)(LPTSTR func, LPTSTR param1); //, LPTSTR param2 = _T(""), LPTSTR param3 = _T(""), LPTSTR param4 = _T(""), LPTSTR param5 = _T(""), LPTSTR param6 = _T(""), LPTSTR param7 = _T(""), LPTSTR param8 = _T(""), LPTSTR param9 = _T(""), LPTSTR param10 = _T("")
	typedef int(*pahkPostFunction)(LPTSTR func, LPTSTR param1); //, LPTSTR param2 = _T(""), LPTSTR param3 = _T(""), LPTSTR param4 = _T(""), LPTSTR param5 = _T(""), LPTSTR param6 = _T(""), LPTSTR param7 = _T(""), LPTSTR param8 = _T(""), LPTSTR param9 = _T(""), LPTSTR param10 = _T("")
	typedef UINT_PTR(*paddFile)(LPTSTR fileName, int waitexecute);
	typedef UINT_PTR(*paddScript)(LPTSTR script, int waitexecute);
	typedef int(*pahkExec)(LPTSTR script);
	typedef UINT_PTR(*pahkdll)(LPTSTR fileName, LPTSTR argv, LPTSTR args);
	typedef UINT_PTR(*pahktextdll)(LPTSTR fileName, LPTSTR argv, LPTSTR args);
	typedef int(*pahkTerminate)(int timeout);
	typedef int(*pahkReady)();
	typedef int(*pahkReload)(int timeout);
	typedef int(*pahkIsUnicode)();
	pahkPause ahkPause;
	pahkFindLabel ahkFindLabel;
	pahkgetvar ahkgetvar;
	pahkassign ahkassign;
	pahkExecuteLine ahkExecuteLine;
	pahkLabel ahkLabel;
	pahkFindFunc ahkFindFunc;
	pahkFunction ahkFunction;
	pahkPostFunction ahkPostFunction;
	paddFile addFile;
	paddScript addScript;
	pahkExec ahkExec;
	pahkdll ahkdll;
	pahktextdll ahktextdll;
	pahkTerminate ahkTerminate;
	pahkReady ahkReady;
	pahkIsUnicode ahkIsUnicode;
		ahkPause = (pahkPause)GetProcAddress(hInstLibrary, "ahkPause");
		ahkFindLabel = (pahkFindLabel)GetProcAddress(hInstLibrary, "ahkFindLabel");
		ahkgetvar = (pahkgetvar)GetProcAddress(hInstLibrary, "ahkgetvar");
		ahkassign = (pahkassign)GetProcAddress(hInstLibrary, "ahkassign");
		ahkExecuteLine = (pahkExecuteLine)GetProcAddress(hInstLibrary, "ahkExecuteLine");
		ahkLabel = (pahkLabel)GetProcAddress(hInstLibrary, "ahkLabel");
		ahkFindFunc = (pahkFindFunc)GetProcAddress(hInstLibrary, "ahkFindFunc");
		ahkFunction = (pahkFunction)GetProcAddress(hInstLibrary, "ahkFunction");
		ahkPostFunction = (pahkPostFunction)GetProcAddress(hInstLibrary, "ahkPostFunction");
		addFile = (paddFile)GetProcAddress(hInstLibrary, "addFile");
		addScript = (paddScript)GetProcAddress(hInstLibrary, "addScript");
		ahkExec = (pahkExec)GetProcAddress(hInstLibrary, "ahkExec");
		ahkdll = (pahkdll)GetProcAddress(hInstLibrary, "ahkdll");
		ahktextdll = (pahktextdll)GetProcAddress(hInstLibrary, "ahktextdll");
		ahkTerminate = (pahkTerminate)GetProcAddress(hInstLibrary, "ahkTerminate");
		ahkReady = (pahkReady)GetProcAddress(hInstLibrary, "ahkReady");
		ahkIsUnicode = (pahkIsUnicode)GetProcAddress(hInstLibrary, "ahkIsUnicode");

The error appeared when calling ahkdll and addFile, but it works with the following:

	typedef UINT(*pahkdll)(LPTSTR script, LPTSTR p1, LPTSTR p2);
	typedef UINT(*pahktextdll)(LPTSTR script, LPTSTR p1, LPTSTR p2);
	typedef UINT_PTR(*paddFile)(LPTSTR script, LPTSTR p1, LPTSTR p2);
	typedef BOOL(*pahkExec)(LPTSTR script);
	typedef UINT(*pahkFunction)(LPTSTR function, LPTSTR pars);
	typedef BOOL(*pahkReady)(void);
	typedef UINT_PTR(*pahkFindFunc)(LPTSTR funcname);
	pahkdll ahkdll;
	pahktextdll ahktextdll;
	paddFile addFile;
	pahkExec ahkExec;
	pahkFunction ahkFunction;
	pahkReady ahkReady;
	pahkFindFunc ahkFindFunc;
		ahkdll = (pahkdll)GetProcAddress(hInstLibrary, "ahkdll");
		ahktextdll = (pahktextdll)GetProcAddress(hInstLibrary, "ahktextdll");
		addFile = (paddFile)GetProcAddress(hInstLibrary, "addFile");
		ahkExec = (pahkExec)GetProcAddress(hInstLibrary, "ahkExec");
		ahkFunction = (pahkFunction)GetProcAddress(hInstLibrary, "ahkFunction");
		ahkReady = (pahkReady)GetProcAddress(hInstLibrary, "ahkReady");
		ahkFindFunc = (pahkFindFunc)GetProcAddress(hInstLibrary, "ahkFindFunc");


HotKeyIt
  • Moderators
  • 7439 posts
  • Last active: Jun 22 2016 09:14 PM
  • Joined: 18 Jun 2008
typedef int(*tcoolfunc)();
tcoolfunc function = (tcoolfunc)dll.ahkFindFunc((wchar_t*)L"coolfunc");
function(); //<--Here comes the error

You can't do that, ahk function is not c++ function and you can't call it that way.

You need to use ahkFunction or ahkPostFunction to call a script function.

You might try calling RegisterCallBack("MyFunction","F",ParamCount) in script using ahkFunction to create a callable pointer for c++, note that a string is returned and you will need to convert it to number EXPORT LPTSTR ahkFunction(LPTSTR func, LPTSTR param1 = _T(""), LPTSTR param2 = _T(""), ...);.

 

Which version are you using, v1 or v2, Unicode or Ansi, from which folder?

Try simply defining ahktextdll and calling ahktextdll(_T("MsgBox"),_T(""),_T("")).



alvitawa
  • Members
  • 98 posts
  • Last active: Oct 14 2017 02:16 PM
  • Joined: 07 Feb 2013

Ok thanks! I dont get that error much right now, so I'l just go on until I get it again :). I am using v1 Win32w



Oowa17
  • Members
  • 3 posts
  • Last active: Dec 13 2014 03:27 PM
  • Joined: 11 Dec 2014

HotKeylt can u please give me a spam hotkey like f1-f9 that can bypass harmony because all my macros is not working because of the harmony. Thanks!!



HotKeyIt
  • Moderators
  • 7439 posts
  • Last active: Jun 22 2016 09:14 PM
  • Joined: 18 Jun 2008

Have a look here.