def __init__(self, argument=None): self.name = None self._objects = {keepalive_key(0): self} self._needs_free = True if isinstance(argument, (int, long)): ffiargs, ffires = self._ffishapes(self._argtypes_, self._restype_) self._ptr = _rawffi.FuncPtr(argument, ffiargs, ffires) self._buffer = self._ptr.byptr() elif callable(argument): self.callable = argument ffiargs, ffires = self._ffishapes(self._argtypes_, self._restype_) self._ptr = _rawffi.CallbackPtr( self._wrap_callable(argument, self.argtypes), ffiargs, ffires) self._buffer = self._ptr.byptr() elif isinstance(argument, tuple) and len(argument) == 2: import ctypes self.name, self.dll = argument if isinstance(self.dll, str): self.dll = ctypes.CDLL(self.dll) # we need to check dll anyway ptr = self._getfuncptr([], ctypes.c_int) self._buffer = ptr.byptr() elif argument is None: # this is needed for casts self._buffer = _rawffi.Array('P')(1) return else: raise TypeError("Unknown constructor %s" % (argument, ))
def _getfuncptr(self, argtypes, restype, thisarg=None): if self._ptr is not None and argtypes is self._argtypes_: return self._ptr if restype is None or not isinstance(restype, _CDataMeta): import ctypes restype = ctypes.c_int argshapes = [arg._ffiargshape for arg in argtypes] resshape = restype._ffiargshape if self._buffer is not None: ptr = _rawffi.FuncPtr(self._buffer[0], argshapes, resshape, self._flags_) if argtypes is self._argtypes_: self._ptr = ptr return ptr if self._com_index: # extract the address from the object's virtual table if not thisarg: raise ValueError("COM method call without VTable") ptr = thisarg[self._com_index - 0x1000] return _rawffi.FuncPtr(ptr, argshapes, resshape, self._flags_) cdll = self.dll._handle try: return cdll.ptr(self.name, argshapes, resshape, self._flags_) except AttributeError: if self._flags_ & _rawffi.FUNCFLAG_CDECL: raise # Win64 has no stdcall calling conv, so it should also not have the # name mangling of it. if WIN64: raise # For stdcall, try mangled names: # funcname -> _funcname@<n> # where n is 0, 4, 8, 12, ..., 128 for i in range(33): mangled_name = "_%s@%d" % (self.name, i * 4) try: return cdll.ptr(mangled_name, argshapes, resshape, self._flags_) except AttributeError: pass raise
def _getfuncptr(self, argtypes, restype): if self._ptr is not None: return self._ptr if restype is None or not isinstance(restype, _CDataMeta): import ctypes restype = ctypes.c_int argshapes = [arg._ffiargshape for arg in argtypes] resshape = restype._ffiargshape if self._buffer is not None: self._ptr = _rawffi.FuncPtr(self._buffer[0], argshapes, resshape) return self._ptr return self.dll._handle.ptr(self.name, argshapes, resshape)
def __init__(self, *args): self.name = None self._objects = {keepalive_key(0): self} self._needs_free = True argument = None if len(args) == 1: argument = args[0] if isinstance(argument, (int, long)): # direct construction from raw address ffiargs, ffires = self._ffishapes(self._argtypes_, self._restype_) self._ptr = _rawffi.FuncPtr(argument, ffiargs, ffires, self._flags_) self._buffer = self._ptr.byptr() elif callable(argument): # A callback into python self.callable = argument ffiargs, ffires = self._ffishapes(self._argtypes_, self._restype_) self._ptr = _rawffi.CallbackPtr( self._wrap_callable(argument, self.argtypes), ffiargs, ffires, self._flags_) self._buffer = self._ptr.byptr() elif isinstance(argument, tuple) and len(argument) == 2: # function exported from a shared library import ctypes self.name, self.dll = argument if isinstance(self.dll, str): self.dll = ctypes.CDLL(self.dll) # we need to check dll anyway ptr = self._getfuncptr([], ctypes.c_int) self._buffer = ptr.byptr() elif (sys.platform == 'win32' and len(args) >= 2 and isinstance(args[0], (int, long))): # A COM function call, by index ffiargs, ffires = self._ffishapes(self._argtypes_, self._restype_) self._com_index = args[0] + 0x1000 self.name = args[1] if len(args) > 2: self._paramflags = args[2] # XXX ignored iid = args[3] elif len(args) == 0: # Empty function object. # this is needed for casts self._buffer = _rawffi.Array('P')(1) return else: raise TypeError("Unknown constructor %s" % (args, ))
def test_raw_callable(self): import _rawffi lib = _rawffi.CDLL(self.lib_name) get_raw_pointer = lib.ptr('get_raw_pointer', [], 'P') ptr = get_raw_pointer() rawcall = _rawffi.FuncPtr(ptr[0], ['h', 'h'], 'H') A = _rawffi.Array('h') arg1 = A(1) arg2 = A(1) arg1[0] = 1 arg2[0] = 2 res = rawcall(arg1, arg2) assert res[0] == 3 arg1.free() arg2.free() assert rawcall.buffer == ptr[0] ptr = rawcall.byptr() assert ptr[0] == rawcall.buffer ptr.free()
def test_raw_callable_returning_void(self): import _rawffi _rawffi.FuncPtr(0, [], None)
def __init__(self, *args): self.name = None self._objects = {keepalive_key(0): self} self._needs_free = True # Empty function object -- this is needed for casts if not args: self._buffer = _rawffi.Array('P')(1) return argsl = list(args) argument = argsl.pop(0) # Direct construction from raw address if isinstance(argument, (int, long)) and not argsl: ffiargs, ffires = self._ffishapes(self._argtypes_, self._restype_) self._ptr = _rawffi.FuncPtr(argument, ffiargs, ffires, self._flags_) self._buffer = self._ptr.byptr() return # A callback into Python if callable(argument) and not argsl: self.callable = argument ffiargs, ffires = self._ffishapes(self._argtypes_, self._restype_) if self._restype_ is None: ffires = None self._ptr = _rawffi.CallbackPtr( self._wrap_callable(argument, self.argtypes), ffiargs, ffires, self._flags_) self._buffer = self._ptr.byptr() return # Function exported from a shared library if isinstance(argument, tuple) and len(argument) == 2: import ctypes self.name, dll = argument if isinstance(dll, str): self.dll = ctypes.CDLL(dll) else: self.dll = dll if argsl: self.paramflags = argsl.pop(0) if argsl: raise TypeError("Unknown constructor %s" % (args, )) # We need to check dll anyway ptr = self._getfuncptr([], ctypes.c_int) self._buffer = ptr.byptr() return # A COM function call, by index if (sys.platform == 'win32' and isinstance(argument, (int, long)) and argsl): ffiargs, ffires = self._ffishapes(self._argtypes_, self._restype_) self._com_index = argument + 0x1000 self.name = argsl.pop(0) if argsl: self.paramflags = argsl.pop(0) if argsl: self._com_iid = argsl.pop(0) if argsl: raise TypeError("Unknown constructor %s" % (args, )) return raise TypeError("Unknown constructor %s" % (args, ))