Ctypes example wraps "MessageBoxA" example didn't work in python33

This example is provided in the python 3.3.2 doc file:

http://docs.python.org/3/library/ctypes.html?highlight=ctypes#ctypes

BUT: when I try it in the interpreter, I get an error message.

I am using windows7 32 python 3.3.2.

Please, help.

from ctypes import c_int, WINFUNCTYPE, windll from ctypes.wintypes import HWND, LPCSTR, UINT prototype = WINFUNCTYPE(c_int, HWND, LPCSTR, LPCSTR, UINT) paramflags = (1, "hwnd", 0), (1, "text", "Hi"), (1, "caption", None), (1, "flags", 0) MessageBox = prototype(("MessageBoxA", windll.user32), paramflags) MessageBox() MessageBox(text="Spam, spam, spam") MessageBox(flags=2, text="foo bar") error message: Traceback (most recent call last): File "<string>", line 250, in run_nodebug File "<g1>", line 7, in <module> ctypes.ArgumentError: argument 2: <class 'TypeError'>: wrong type 
+4
source share
1 answer

Guess this is a bug in the documentation .; -)

In Python 3, all strings are Unicode by default, but the example calls the ANSI MessageBoxA function, not the MessageBoxW version of Unicode. See 16.17.1.2. Access to functions from loaded ctypes in ctypes documentation.

So, for MessageBoxA in this example, you can make it work by encoding the arguments of the input lines of the function to what is required by calling locale.getpreferredencoding() :

 from ctypes import c_int, WINFUNCTYPE, windll from ctypes.wintypes import HWND, LPCSTR, UINT import locale preferred_encoding = locale.getpreferredencoding(False) prototype = WINFUNCTYPE(c_int, HWND, LPCSTR, LPCSTR, UINT) paramflags = ((1, "hwnd", 0), (1, "text", "Hi".encode(preferred_encoding)), (1, "caption", None), (1, "flags", 0)) MessageBox = prototype(("MessageBoxA", windll.user32), paramflags) MessageBox() MessageBox(text="Spam, spam, spam".encode(preferred_encoding)) MessageBox(flags=2, text="foo bar".encode(preferred_encoding)) 

It would be much more inconvenient to use the MessageBoxW function of Windows, which supports Unicode "wide" string arguments ( LPCWSTR instead of LPCSTR ), which makes them explicitly encoded on almost every call unnecessary. In addition, I would replace most of the "magic numbers" in the example with named constants:

 from ctypes import c_int, WINFUNCTYPE, windll from ctypes.wintypes import HWND, LPCWSTR, UINT import win32con # contains Win32 constants pulled from the C header files INPUT_PARM, OUTPUT_PARAM, INPUT_PARM_DEFAULT_ZERO = 1, 2, 4 prototype = WINFUNCTYPE(c_int, HWND, LPCWSTR, LPCWSTR, UINT) paramflags = ((INPUT_PARM, "hwnd", 0), (INPUT_PARM, "text", "Hi"), (INPUT_PARM, "caption", None), (INPUT_PARM, "flags", win32con.MB_HELP)) MessageBox = prototype(("MessageBoxW", windll.user32), paramflags) MessageBox() MessageBox(text="Spam, spam, spam") MessageBox(flags=win32con.MB_ABORTRETRYIGNORE, text="foo bar") 
+6
source

Source: https://habr.com/ru/post/1496344/


All Articles