def IUnknown_QueryInterface(self, this, riid, ppvObj, _debug=_debug): # XXX This is probably too slow. # riid[0].hashcode() alone takes 33 us! iid = riid[0] ptr = self._com_pointers_.get(iid, None) if ptr is not None: # CopyComPointer(src, dst) calls AddRef! _debug("%r.QueryInterface(%s) -> S_OK", self, iid) return CopyComPointer(ptr, ppvObj) _debug("%r.QueryInterface(%s) -> E_NOINTERFACE", self, iid) return E_NOINTERFACE
def QueryInterface(self, interface): "Query the object for an interface pointer" # This method is NOT the implementation of # IUnknown::QueryInterface, instead it is supposed to be # called on an COMObject by user code. It allows to get COM # interface pointers from COMObject instances. ptr = self._com_pointers_.get(interface._iid_, None) if ptr is None: raise COMError(E_NOINTERFACE, FormatError(E_NOINTERFACE), (None, None, 0, None, None)) # CopyComPointer(src, dst) calls AddRef! result = POINTER(interface)() CopyComPointer(ptr, byref(result)) return result
def __setitem__(self, index, value): # We override the __setitem__ method of the # POINTER(POINTER(interface)) type, so that the COM # reference count is managed correctly. # # This is so that we can implement COM methods that have to # return COM pointers more easily and consistent. Instead of # using CopyComPointer in the method implementation, we can # simply do: # # def GetTypeInfo(self, this, ..., pptinfo): # if not pptinfo: return E_POINTER # pptinfo[0] = a_com_interface_pointer # return S_OK if index != 0: # CopyComPointer, which is in _ctypes, does only # handle an index of 0. This code does what # CopyComPointer should do if index != 0. if bool(value): value.AddRef() super(_, self).__setitem__(index, value) return from _ctypes import CopyComPointer CopyComPointer(value, self)
def _set_value(self, value): _VariantClear(self) if value is None: self.vt = VT_NULL elif hasattr(value, '__len__') and len(value) == 0: self.vt = VT_NULL # since bool is a subclass of int, this check must come before # the check for int elif isinstance(value, bool): self.vt = VT_BOOL self._.VT_BOOL = value elif isinstance(value, (int, c_int)): self.vt = VT_I4 self._.VT_I4 = value elif isinstance(value, long): u = self._ # try VT_I4 first. u.VT_I4 = value if u.VT_I4 == value: # it did work. self.vt = VT_I4 return # try VT_UI4 next. if value >= 0: u.VT_UI4 = value if u.VT_UI4 == value: # did work. self.vt = VT_UI4 return # try VT_I8 next. if value >= 0: u.VT_I8 = value if u.VT_I8 == value: # did work. self.vt = VT_I8 return # try VT_UI8 next. if value >= 0: u.VT_UI8 = value if u.VT_UI8 == value: # did work. self.vt = VT_UI8 return # VT_R8 is last resort. self.vt = VT_R8 u.VT_R8 = float(value) elif isinstance(value, (float, c_double)): self.vt = VT_R8 self._.VT_R8 = value elif isinstance(value, (str, unicode)): self.vt = VT_BSTR # do the c_wchar_p auto unicode conversion self._.c_void_p = _SysAllocStringLen(value, len(value)) elif isinstance(value, datetime.datetime): delta = value - _com_null_date # a day has 24 * 60 * 60 = 86400 seconds com_days = delta.days + (delta.seconds + delta.microseconds * 1e-6) / 86400. self.vt = VT_DATE self._.VT_R8 = com_days elif npsupport.isdatetime64(value): com_days = value - npsupport.com_null_date64 com_days /= npsupport.numpy.timedelta64(1, 'D') self.vt = VT_DATE self._.VT_R8 = com_days elif decimal is not None and isinstance(value, decimal.Decimal): self._.VT_CY = int(round(value * 10000)) self.vt = VT_CY elif isinstance(value, POINTER(IDispatch)): CopyComPointer(value, byref(self._)) self.vt = VT_DISPATCH elif isinstance(value, POINTER(IUnknown)): CopyComPointer(value, byref(self._)) self.vt = VT_UNKNOWN elif isinstance(value, (list, tuple)): obj = _midlSAFEARRAY(VARIANT).create(value) memmove(byref(self._), byref(obj), sizeof(obj)) self.vt = VT_ARRAY | obj._vartype_ elif isinstance(value, array.array): vartype = _arraycode_to_vartype[value.typecode] typ = _vartype_to_ctype[vartype] obj = _midlSAFEARRAY(typ).create(value) memmove(byref(self._), byref(obj), sizeof(obj)) self.vt = VT_ARRAY | obj._vartype_ elif npsupport.isndarray(value): # Try to convert a simple array of basic types. descr = value.dtype.descr[0][1] typ = npsupport.numpy.ctypeslib._typecodes.get(descr) if typ is None: # Try for variant obj = _midlSAFEARRAY(VARIANT).create(value) else: obj = _midlSAFEARRAY(typ).create(value) memmove(byref(self._), byref(obj), sizeof(obj)) self.vt = VT_ARRAY | obj._vartype_ elif isinstance(value, Structure) and hasattr(value, "_recordinfo_"): guids = value._recordinfo_ from comtypes.typeinfo import GetRecordInfoFromGuids ri = GetRecordInfoFromGuids(*guids) self.vt = VT_RECORD # Assigning a COM pointer to a structure field does NOT # call AddRef(), have to call it manually: ri.AddRef() self._.pRecInfo = ri self._.pvRecord = ri.RecordCreateCopy(byref(value)) elif isinstance(getattr(value, "_comobj", None), POINTER(IDispatch)): CopyComPointer(value._comobj, byref(self._)) self.vt = VT_DISPATCH elif isinstance(value, VARIANT): _VariantCopy(self, value) elif isinstance(value, c_ubyte): self._.VT_UI1 = value self.vt = VT_UI1 elif isinstance(value, c_char): self._.VT_UI1 = ord(value.value) self.vt = VT_UI1 elif isinstance(value, c_byte): self._.VT_I1 = value self.vt = VT_I1 elif isinstance(value, c_ushort): self._.VT_UI2 = value self.vt = VT_UI2 elif isinstance(value, c_short): self._.VT_I2 = value self.vt = VT_I2 elif isinstance(value, c_uint): self.vt = VT_UI4 self._.VT_UI4 = value elif isinstance(value, c_float): self.vt = VT_R4 self._.VT_R4 = value elif isinstance(value, c_int64): self.vt = VT_I8 self._.VT_I8 = value elif isinstance(value, c_uint64): self.vt = VT_UI8 self._.VT_UI8 = value elif isinstance(value, _byref_type): ref = value._obj self._.c_void_p = addressof(ref) self.__keepref = value self.vt = _ctype_to_vartype[type(ref)] | VT_BYREF elif isinstance(value, _Pointer): ref = value.contents self._.c_void_p = addressof(ref) self.__keepref = value self.vt = _ctype_to_vartype[type(ref)] | VT_BYREF else: raise TypeError("Cannot put %r in VARIANT" % value)