Call functions in AutoIt DLL using Python ctypes
Asked Answered
F

2

6

I want to call functions from an AutoIt dll, that I found at C:\Program Files (x86)\AutoIt3\AutoItX\AutoItX3.dll using Python. I know I could use win32com.client.Dispatch("AutoItX3.Control") but I can't install the application or register anything in the system.

So far, this is where I am:

from ctypes import *
path = r"C:\Program Files (x86)\AutoIt3\AutoItX\AutoItX3.dll"
autoit = windll.LoadLibrary(path)

Here are the methods that works:

autoit.AU3_WinMinimizeAll() # windows were successfully minimized.
autoit.AU3_Sleep(1000) # sleeps 1 sec.

Here is my problem, python is crashing when I call other methods like this one. I get python.exe has stopped working from windows...

autoit.AU3_WinGetHandle('Untitled - Notepad', '')

And some other methods are not crashing python but are just not working. This one doesn't close the window and return 0:

autoit.AU3_WinClose('Untitled - Notepad', '')

And this other one return 1 but the window is still minimized:

autoit.AU3_WinActivate('Untitled - Notepad', '')

I've tested the examples with with Dispatch("AutoItX3.Control") and everything is working like expected.

It seems like methods that should return something other than a string are crashing python. But still, others like WinClose are not even working...

Thank you in advance for your help!

EDIT:

These methods are now working when using unicode strings:

autoit.AU3_WinClose(u'Untitled - Notepad', u'')
autoit.AU3_WinActivate(u'Untitled - Notepad', u'')

And I found the prototype for AU3_WinGetHandle:

AU3_API void WINAPI AU3_WinGetHandle(const char szTitle, /[in,defaultvalue("")]*/const char *szText, char *szRetText, int nBufSize);

Now I can retrieve the return value using the following code!

from ctypes.wintypes import LPCWSTR
s = LPCWSTR(u'')
print AU3_WinGetHandle(u'Untitled - Notepad', u'', s, 100) # prints 1
print s.value # prints '000705E0'!

Thank you to those who helped me!

Frodin answered 13/11, 2013 at 2:10 Comment(1)
Do you know the right prototypes for these functions? If so, you should set the argtypes and restype for each function, instead of just calling it. That way, if Python can convert your arguments to the correct type it will, and otherwise it will give you an error. The way you're doing it, Python has to guess which type it should convert to, and if it guesses wrong, you'll crash.Spongin
S
4

If you have the prototypes of the functions you're trying to call, then we can help you debug the calls without guessing. Or, more importantly, we won't have to help you debug the calls, because you can let ctypes do it for you.

See Specifying the required argument types in the docs.

For example, let's say the function looks like this (just a random guess!):

void AU3_WinClose(LPCWSTR name, LPCWSTR someotherthing);

You can do this:

autoit.AU3_WinClose.argtypes = (LPCWSTR, LPCWSTR)
autoit.AU3_WinClose.restype = None

If you do this, ctypes will try to convert your arguments to the specified types (LPWSTR, which is a pointer to wide char used for Windows UTF-16 strings) if it can, or raise an exception if it can't, and will not expect any return value.

If you don't do this, ctypes will try to guess the right things to convert your arguments to, possibly guessing wrong, and will try to interpret the non-existent return value as an int. So, it will usually crash until you managed to guess exactly what types to throw at it to make it guess the right types to pass to the function.

Spongin answered 13/11, 2013 at 2:42 Comment(1)
Thank you, I am getting closer! I edited my question, I found the prototype but I don't know how to get the return value from a pointer...Frodin
B
4

Will it work with unicode strings?

autoit.AU3_WinClose(u'Untitled - Notepad', u'')

autoit.AU3_WinActivate(u'Untitled - Notepad', u'')

Actually you might have to explicitly create unicode buffers, e.g.:

autoit.AU3_WinClose(create_unicode_buffer('Untitled - Notepad'), create_unicode_buffer(''))

Via some Googling, it looks like AU3_WinGetHandle takes 4 arguments, not 2. So you need to get that sorted out.

Benzofuran answered 13/11, 2013 at 2:31 Comment(3)
Or, better, just set autoit.AU3_WinClose.argtypes=(LPCWSTR, LPCWSTR) and let ctypes automatically create the buffers and do any other conversion. Trying to do this stuff manually is a lot of extra work, and very easy to get wrong, usually leading to a crash if you're lucky.Spongin
Good guess on the problem, but from a quick search for AU3_WinClose prototype, I got this thread, where it appears to be //AU3_API long WINAPI AU3_WinClose(const char *szTitle, /*[in,defaultvalue("")]*/const char *szText);—in other words, 8-bit strings, not Unicode, and they're const so we don't need to create a mutable buffer. Maybe it's the long return value?Spongin
I will!, as soon as I have enough reputation! :-)Frodin
S
4

If you have the prototypes of the functions you're trying to call, then we can help you debug the calls without guessing. Or, more importantly, we won't have to help you debug the calls, because you can let ctypes do it for you.

See Specifying the required argument types in the docs.

For example, let's say the function looks like this (just a random guess!):

void AU3_WinClose(LPCWSTR name, LPCWSTR someotherthing);

You can do this:

autoit.AU3_WinClose.argtypes = (LPCWSTR, LPCWSTR)
autoit.AU3_WinClose.restype = None

If you do this, ctypes will try to convert your arguments to the specified types (LPWSTR, which is a pointer to wide char used for Windows UTF-16 strings) if it can, or raise an exception if it can't, and will not expect any return value.

If you don't do this, ctypes will try to guess the right things to convert your arguments to, possibly guessing wrong, and will try to interpret the non-existent return value as an int. So, it will usually crash until you managed to guess exactly what types to throw at it to make it guess the right types to pass to the function.

Spongin answered 13/11, 2013 at 2:42 Comment(1)
Thank you, I am getting closer! I edited my question, I found the prototype but I don't know how to get the return value from a pointer...Frodin

© 2022 - 2024 — McMap. All rights reserved.