Skip to content

unexpected ctypes traceback in python 3.12.0 on Windows #111150

@ccanepa

Description

@ccanepa

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?

  • ctypes_test.zip

CPython versions tested on:

3.8, 3.11, 3.12

Operating systems tested on:

Windows

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions