(ctype)
return ctype
Modify the given ctypes type so it can be returned from a callback function.

    This function may be used as a decorator on a struct/union declaration.

    The method is idempotent; it only modifies the type the first time it
    is invoked on a type.
Modify the given ctypes type so it can be returned from a callback function.
Modify the given ctypes type so it can be returned from a callback function .
def make_callback_returnable(ctype):
    """Modify the given ctypes type so it can be returned from a callback function.

    This function may be used as a decorator on a struct/union declaration.

    The method is idempotent; it only modifies the type the first time it
    is invoked on a type.
    """
    # The presence of the _rubicon_objc_ctypes_patch_getfunc attribute is a
    # sentinel for whether the type has been modified previously.
    if hasattr(ctype, '_rubicon_objc_ctypes_patch_getfunc'):
        return ctype

    # Extract the StgDict from the ctype.
    stgdict = get_stgdict_of_type(ctype)
    stgdict_c = StgDictObject.from_address(id(stgdict))

    # Ensure that there is no existing getfunc or setfunc on the stgdict.
    if ctypes.cast(stgdict_c.getfunc, ctypes.c_void_p).value is not None:
        raise ValueError("The ctype {}.{} already has a getfunc".format(ctype.__module__, ctype.__name__))
    elif ctypes.cast(stgdict_c.setfunc, ctypes.c_void_p).value is not None:
        raise ValueError("The ctype {}.{} already has a setfunc".format(ctype.__module__, ctype.__name__))

    # Define the getfunc and setfunc.
    @GETFUNC
    def getfunc(ptr, size):
        actual_size = ctypes.sizeof(ctype)
        if size != 0 and size != actual_size:
            raise ValueError(
                "getfunc for ctype {}: Requested size {} does not match actual size {}"
                .format(ctype, size, actual_size)
            )

        return ctype.from_buffer_copy(ctypes.string_at(ptr, actual_size))

    @SETFUNC
    def setfunc(ptr, value, size):
        actual_size = ctypes.sizeof(ctype)
        if size != 0 and size != actual_size:
            raise ValueError(
                "setfunc for ctype {}: Requested size {} does not match actual size {}"
                .format(ctype, size, actual_size)
            )

        ctypes.memmove(ptr, ctypes.addressof(value), actual_size)
        # Because of ctypes bug bpo-36880 (https://bugs.python.org/issue36880), returning None from a callback with
        # restype py_object causes a reference counting error that can crash Python.
        # To work around this bug, the restype of SETFUNC is declared as c_void_p instead.
        # This way ctypes performs no automatic reference counting for the returned object, which avoids the bug.
        # However, this way we have to manually convert the Python object to a pointer and adjust its reference count.
        none_ptr = ctypes.cast(id(None), ctypes.POINTER(PyObject))
        # The return value of a SETFUNC is expected to have an extra reference
        # (which will be owned by the caller of the SETFUNC).
        ctypes.pythonapi.Py_IncRef(none_ptr)
        # The returned pointer must be returned as a plain int, not as a c_void_p,
        # otherwise ctypes won't recognize it and will raise a TypeError.
        return ctypes.cast(none_ptr, ctypes.c_void_p).value

    # Store the getfunc and setfunc as attributes on the ctype, so they don't get garbage-collected.
    ctype._rubicon_objc_ctypes_patch_getfunc = getfunc
    ctype._rubicon_objc_ctypes_patch_setfunc = setfunc
    # Put the getfunc and setfunc into the stgdict fields.
    stgdict_c.getfunc = getfunc
    stgdict_c.setfunc = setfunc

    # Return the passed in ctype, so this function can be used as a decorator.
    return ctype
def make_callback_returnable ( ctype ) : # The presence of the _rubicon_objc_ctypes_patch_getfunc attribute is a # sentinel for whether the type has been modified previously. if hasattr ( ctype , '_rubicon_objc_ctypes_patch_getfunc' ) : return ctype # Extract the StgDict from the ctype. stgdict = get_stgdict_of_type ( ctype ) stgdict_c = StgDictObject . from_address ( id ( stgdict ) ) # Ensure that there is no existing getfunc or setfunc on the stgdict. if ctypes . cast ( stgdict_c . getfunc , ctypes . c_void_p ) . value is not None : raise ValueError ( "The ctype {}.{} already has a getfunc" . format ( ctype . __module__ , ctype . __name__ ) ) elif ctypes . cast ( stgdict_c . setfunc , ctypes . c_void_p ) . value is not None : raise ValueError ( "The ctype {}.{} already has a setfunc" . format ( ctype . __module__ , ctype . __name__ ) ) # Define the getfunc and setfunc. @ GETFUNC def getfunc ( ptr , size ) : actual_size = ctypes . sizeof ( ctype ) if size != 0 and size != actual_size : raise ValueError ( "getfunc for ctype {}: Requested size {} does not match actual size {}" . format ( ctype , size , actual_size ) ) return ctype . from_buffer_copy ( ctypes . string_at ( ptr , actual_size ) ) @ SETFUNC def setfunc ( ptr , value , size ) : actual_size = ctypes . sizeof ( ctype ) if size != 0 and size != actual_size : raise ValueError ( "setfunc for ctype {}: Requested size {} does not match actual size {}" . format ( ctype , size , actual_size ) ) ctypes . memmove ( ptr , ctypes . addressof ( value ) , actual_size ) # Because of ctypes bug bpo-36880 (https://bugs.python.org/issue36880), returning None from a callback with # restype py_object causes a reference counting error that can crash Python. # To work around this bug, the restype of SETFUNC is declared as c_void_p instead. # This way ctypes performs no automatic reference counting for the returned object, which avoids the bug. # However, this way we have to manually convert the Python object to a pointer and adjust its reference count. none_ptr = ctypes . cast ( id ( None ) , ctypes . POINTER ( PyObject ) ) # The return value of a SETFUNC is expected to have an extra reference # (which will be owned by the caller of the SETFUNC). ctypes . pythonapi . Py_IncRef ( none_ptr ) # The returned pointer must be returned as a plain int, not as a c_void_p, # otherwise ctypes won't recognize it and will raise a TypeError. return ctypes . cast ( none_ptr , ctypes . c_void_p ) . value # Store the getfunc and setfunc as attributes on the ctype, so they don't get garbage-collected. ctype . _rubicon_objc_ctypes_patch_getfunc = getfunc ctype . _rubicon_objc_ctypes_patch_setfunc = setfunc # Put the getfunc and setfunc into the stgdict fields. stgdict_c . getfunc = getfunc stgdict_c . setfunc = setfunc # Return the passed in ctype, so this function can be used as a decorator. return ctype