-
-
Notifications
You must be signed in to change notification settings - Fork 32.4k
Description
Bug report
Bug description:
Code that was working for years with pythons < 3.12.0 now tracebacks in a call to gdiplus.GdipCreateBitmapFromScan0
, a function in the Windows SDK , with error
ctypes.ArgumentError: argument 5: TypeError: expected LP_c_ubyte instance instead of c_byte_Array_3520
Problem traced to PR #97579
where ctypes.wintypes.BYTE changed from ctypes.c_byte to ctypes.c_ubyte
A minimal demo uses
- a dll that defines a function of interest
#define DllExport extern "C" __declspec( dllexport )
// BYTE is defined in the Windows SDK as `typedef unsigned char BYTE;`
DllExport void replaces_a(BYTE *buf, size_t n) {
if (n <= 0) return;
BYTE *p = buf + n;
while (buf < p) {
p--;
if (*p == 'a') {
*p = 'z';
}
}
}
- a python script that mimics the call context in the original failing code, and a possible workaround (cast) outside of cpython code
import ctypes as ct
from ctypes.wintypes import BYTE
# load library, define ctypes signature for the function of interest
mydll = ct.cdll.LoadLibrary(r"..\bin\test.dll")
mydll.replaces_a.restype = None
mydll.replaces_a.argtypes = [ct.POINTER(BYTE), ct.c_size_t]
# prepare params
size = 12
data = (ctypes.c_byte * size)()
# try the workaround call, using a cast, works fine in 3.8, 3.11 and 3.12
mydll.replaces_a(ct.cast(data, ct.POINTER(BYTE)), size)
# ...
# worked fine, the script shows the expected output
# try the problematic call style, does fine in 3.8 and 3.11, tracebaks in 3.12.0
mydll.replaces_a(data, size)
# in 3.12.0 emits the traceback
Traceback (most recent call last):
File "D:\dev\ctypes_test\src\test_test.py", line 38, in <module>
mydll.replaces_a(data, size)
ctypes.ArgumentError: argument 1: TypeError: expected LP_c_ubyte instance instead of c_byte_Array_12
-
reverting the PR change related to BYTE in the cpython code makes the demo code run without errors.
-
to complete the reproducibility aspect I attached ctypes_test.zip with the dll source and bin, with instructions on how to rebuild if necessary; the python script is in the place it needs to be to find the dll
-
the original glitch I reported at win32_gdi_font tracebacks in python 3.12 pyglet/pyglet#964
-
The ctypes page in python 3.12.0 does not mention any related change (searched all ocurrences of 'change')
-
I don't remember in the 3.12 announcements mentions to potentially breaking changes in ctypes, but maybe there was some?
CPython versions tested on:
3.8, 3.11, 3.12
Operating systems tested on:
Windows