Skip to content

Annotation-based syntax for ctypes structs #104533

Closed

Activity

  1. ZeroIntensity commented on Jul 15, 2026

    @ZeroIntensity
    Member

    The overwhelming support present on this issue, along with the repeated requests from users, has convinced me that this is worth the effort. I've put up an implementation at #153781, which I'll polish and/or merge during the EuroPython sprints this weekend.

  2. added a commit that references this issue on Jul 18, 2026
  3. orent commented on Jul 18, 2026

    @orent
    Author

    The original discussion at https://discuss.python.org/t/annotation-based-sugar-for-ctypes/26579

    Also had a proposal for sugaring the syntax of functions, too:

    This:

    libm = ctypes.CDLL('libm.so')
    pow = libm.pow
    pow.restype = ctypes.c_double
    pow.argtypes = (ctypes.c_double, ctypes, c_double)
    

    into this:

    libm = ctypes.CDLL('libm.so')
    
    @libm
    def pow(a: ctypes.c_double, b:ctypes.c_double) -> c_double:
        pass
    

    Any interest in pursuing this, too?

  4. added a commit that references this issue on Jul 18, 2026
  5. added
    stdlibStandard Library Python modules in the Lib/ directory
    on Jul 18, 2026
  6. ZeroIntensity commented on Jul 18, 2026

    @ZeroIntensity
    Member

    Yes, but let's do that in a new issue. I'm uncomfortable with making CDLL/PyDLL callable like in your example, but a decorator that simply accepts a DLL should be fine:

    @wrap_dll_function(ctypes.pythonapi)
    def PyObject_GetAttrString(op: ctypes.py_object, attr: ctypes.c_char_p) -> ctypes.py_object:
        ...
  7. orent commented on Jul 18, 2026

    @orent
    Author

    @wrap_dll_function(ctypes.pythonapi)
    def PyObject_GetAttrString(op: ctypes.py_object, attr: ctypes.c_char_p) -> ctypes.py_object:
    ...

    Did you mean the ellipsis literally? It’s actually a good idea to require it and have the decorator wrapper verify that the function body consists of an ellipsis as a signal to the reader that the function body is not there.

  8. ZeroIntensity commented on Jul 18, 2026

    @ZeroIntensity
    Member

    I did. Maybe pass should be the documented option? I'm not a big fan of actually trying to validate that the function has no body, because that would involve weird bytecode or AST introspection, which would significantly complicate the implementation.

  9. added 7 commits that reference this issue on Jul 19, 2026
  10. fedonman commented on Sep 23, 2026

    @fedonman
    Contributor

    @ZeroIntensity, a question about ctypes.util.struct: what should it do with a class that subclasses ctypes.Union? Right now it drops the base and builds a Structure, so the fields no longer overlap:

    from ctypes import Union, c_int, c_double, sizeof
    from ctypes.util import struct
    
    @struct
    class U(Union):
        i: c_int
        d: c_double
    
    print(U.__mro__[1].__name__, sizeof(U))
    Structure 16
    

    The docs only promise structure types, so this might be intended. If it isn't, it could either raise TypeError or build a Union. I'm happy to open an issue and a PR for whichever you'd prefer.

  11. ZeroIntensity commented on Sep 23, 2026

    @ZeroIntensity
    Member

    I think it should raise a TypeError. We may want to add a @ctypes.util.union decorator, but I'll handle that separately.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    stdlibStandard Library Python modules in the Lib/ directorytopic-ctypestype-featureA feature request or enhancement

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions