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