def _call_funcptr(self, funcptr, *newargs): if self._flags_ & _rawffi.FUNCFLAG_USE_ERRNO: tmp = _rawffi.get_errno() _rawffi.set_errno(get_errno()) set_errno(tmp) if self._flags_ & _rawffi.FUNCFLAG_USE_LASTERROR: tmp = _rawffi.get_last_error() _rawffi.set_last_error(get_last_error()) set_last_error(tmp) try: result = funcptr(*newargs) finally: if self._flags_ & _rawffi.FUNCFLAG_USE_ERRNO: tmp = _rawffi.get_errno() _rawffi.set_errno(get_errno()) set_errno(tmp) if self._flags_ & _rawffi.FUNCFLAG_USE_LASTERROR: tmp = _rawffi.get_last_error() _rawffi.set_last_error(get_last_error()) set_last_error(tmp) # try: return self._build_result(self._restype_, result) finally: funcptr.free_temp_buffers()
def test_errno_saved_and_restored(self): def check(): assert _rawffi.get_errno() == 42 assert ctypes.get_errno() == old check.free_temp_buffers = lambda *args: None f = function.CFuncPtr() old = _rawffi.get_errno() f._flags_ = _rawffi.FUNCFLAG_USE_ERRNO ctypes.set_errno(42) f._call_funcptr(check) assert _rawffi.get_errno() == old ctypes.set_errno(0)
def _call_funcptr(self, funcptr, *newargs): if self._flags_ & _rawffi.FUNCFLAG_USE_ERRNO: set_errno(_rawffi.get_errno()) if self._flags_ & _rawffi.FUNCFLAG_USE_LASTERROR: set_last_error(_rawffi.get_last_error()) try: result = funcptr(*newargs) finally: if self._flags_ & _rawffi.FUNCFLAG_USE_ERRNO: set_errno(_rawffi.get_errno()) if self._flags_ & _rawffi.FUNCFLAG_USE_LASTERROR: set_last_error(_rawffi.get_last_error()) # return self._build_result(self._restype_, result, newargs)
def test_errno(self): import _rawffi lib = _rawffi.CDLL(self.lib_name) A = _rawffi.Array('i') f = lib.ptr('check_errno', ['i'], 'i') _rawffi.set_errno(42) arg = A(1) arg[0] = 43 res = f(arg) assert res[0] == 42 z = _rawffi.get_errno() assert z == 43 arg.free()
def __call__(self, *args, **kwargs): argtypes = self._argtypes_ if self.callable is not None: if len(args) == len(argtypes): pass elif self._flags_ & _rawffi.FUNCFLAG_CDECL: if len(args) < len(argtypes): plural = len(argtypes) > 1 and "s" or "" raise TypeError( "This function takes at least %d argument%s (%s given)" % (len(argtypes), plural, len(args))) else: # For cdecl functions, we allow more actual arguments # than the length of the argtypes tuple. args = args[:len(self._argtypes_)] else: plural = len(argtypes) > 1 and "s" or "" raise TypeError( "This function takes %d argument%s (%s given)" % (len(argtypes), plural, len(args))) # check that arguments are convertible ## XXX Not as long as ctypes.cast is a callback function with ## py_object arguments... ## self._convert_args(argtypes, args, {}) try: res = self.callable(*args) except: exc_info = sys.exc_info() traceback.print_tb(exc_info[2], file=sys.stderr) print >> sys.stderr, "%s: %s" % (exc_info[0].__name__, exc_info[1]) return 0 if self._restype_ is not None: return res return if argtypes is None: warnings.warn('C function without declared arguments called', RuntimeWarning, stacklevel=2) argtypes = [] if not self.__restype_set: warnings.warn('C function without declared return type called', RuntimeWarning, stacklevel=2) if self._com_index: from ctypes import cast, c_void_p, POINTER if not args: raise ValueError( "native COM method call without 'this' parameter") thisarg = cast(args[0], POINTER(POINTER(c_void_p))).contents argtypes = [c_void_p] + list(argtypes) args = list(args) args[0] = args[0].value else: thisarg = None args, outargs = self._convert_args(argtypes, args, kwargs) argtypes = [type(arg) for arg in args] restype = self._restype_ funcptr = self._getfuncptr(argtypes, restype, thisarg) if self._flags_ & _rawffi.FUNCFLAG_USE_ERRNO: set_errno(_rawffi.get_errno()) if self._flags_ & _rawffi.FUNCFLAG_USE_LASTERROR: set_last_error(_rawffi.get_last_error()) try: resbuffer = funcptr( *[arg._get_buffer_for_param()._buffer for arg in args]) finally: if self._flags_ & _rawffi.FUNCFLAG_USE_ERRNO: set_errno(_rawffi.get_errno()) if self._flags_ & _rawffi.FUNCFLAG_USE_LASTERROR: set_last_error(_rawffi.get_last_error()) result = None if self._com_index: if resbuffer[0] & 0x80000000: raise get_com_error(resbuffer[0], self._com_iid, args[0]) else: result = int(resbuffer[0]) elif restype is not None: checker = getattr(self.restype, '_check_retval_', None) if checker: val = restype(resbuffer[0]) # the original ctypes seems to make the distinction between # classes defining a new type, and their subclasses if '_type_' in restype.__dict__: val = val.value result = checker(val) elif not isinstance(restype, _CDataMeta): result = restype(resbuffer[0]) else: result = restype._CData_retval(resbuffer) # The 'errcheck' protocol if self._errcheck_: v = self._errcheck_(result, self, args) # If the errcheck funtion failed, let it throw # If the errcheck function returned callargs unchanged, # continue normal processing. # If the errcheck function returned something else, # use that as result. if v is not args: result = v if not outargs: return result if len(outargs) == 1: return outargs[0] return tuple(outargs)
def check(): assert _rawffi.get_errno() == 42 assert ctypes.get_errno() == old
def __call__(self, *args, **kwargs): argtypes = self._argtypes_ if self.callable is not None: if len(args) == len(argtypes): pass elif self._flags_ & _rawffi.FUNCFLAG_CDECL: if len(args) < len(argtypes): plural = len(argtypes) > 1 and "s" or "" raise TypeError( "This function takes at least %d argument%s (%s given)" % (len(argtypes), plural, len(args))) else: # For cdecl functions, we allow more actual arguments # than the length of the argtypes tuple. args = args[:len(self._argtypes_)] else: plural = len(argtypes) > 1 and "s" or "" raise TypeError( "This function takes %d argument%s (%s given)" % (len(argtypes), plural, len(args))) # check that arguments are convertible ## XXX Not as long as ctypes.cast is a callback function with ## py_object arguments... ## self._convert_args(argtypes, args, {}) try: res = self.callable(*args) except: exc_info = sys.exc_info() traceback.print_tb(exc_info[2], file=sys.stderr) print >>sys.stderr, "%s: %s" % (exc_info[0].__name__, exc_info[1]) return 0 if self._restype_ is not None: return res return if argtypes is None: warnings.warn('C function without declared arguments called', RuntimeWarning, stacklevel=2) argtypes = [] if not self.__restype_set: warnings.warn('C function without declared return type called', RuntimeWarning, stacklevel=2) if self._com_index: from ctypes import cast, c_void_p, POINTER if not args: raise ValueError( "native COM method call without 'this' parameter" ) thisarg = cast(args[0], POINTER(POINTER(c_void_p))).contents argtypes = [c_void_p] + list(argtypes) args = list(args) args[0] = args[0].value else: thisarg = None args, outargs = self._convert_args(argtypes, args, kwargs) argtypes = [type(arg) for arg in args] restype = self._restype_ funcptr = self._getfuncptr(argtypes, restype, thisarg) if self._flags_ & _rawffi.FUNCFLAG_USE_ERRNO: set_errno(_rawffi.get_errno()) if self._flags_ & _rawffi.FUNCFLAG_USE_LASTERROR: set_last_error(_rawffi.get_last_error()) try: resbuffer = funcptr(*[arg._get_buffer_for_param()._buffer for arg in args]) finally: if self._flags_ & _rawffi.FUNCFLAG_USE_ERRNO: set_errno(_rawffi.get_errno()) if self._flags_ & _rawffi.FUNCFLAG_USE_LASTERROR: set_last_error(_rawffi.get_last_error()) result = None if self._com_index: if resbuffer[0] & 0x80000000: raise get_com_error(resbuffer[0], self._com_iid, args[0]) else: result = int(resbuffer[0]) elif restype is not None: checker = getattr(self.restype, '_check_retval_', None) if checker: val = restype(resbuffer[0]) # the original ctypes seems to make the distinction between # classes defining a new type, and their subclasses if '_type_' in restype.__dict__: val = val.value result = checker(val) elif not isinstance(restype, _CDataMeta): result = restype(resbuffer[0]) else: result = restype._CData_retval(resbuffer) # The 'errcheck' protocol if self._errcheck_: v = self._errcheck_(result, self, args) # If the errcheck funtion failed, let it throw # If the errcheck function returned callargs unchanged, # continue normal processing. # If the errcheck function returned something else, # use that as result. if v is not args: result = v if not outargs: return result if len(outargs) == 1: return outargs[0] return tuple(outargs)