def variant_array(value): from ctypes import (POINTER, Structure, byref, cast, c_long, c_float, c_double, memmove, pointer, sizeof) from comtypes import _safearray, IUnknown, com_interface_registry from comtypes.automation import VARIANT, VT_VARIANT, VT_SAFEARRAY, VT_ARRAY, tagVARIANT, VT_DISPATCH from comtypes.safearray import _midlSAFEARRAY vartype = VT_DISPATCH itemtype = VARIANT cls = _midlSAFEARRAY(itemtype) rgsa = (_safearray.SAFEARRAYBOUND * 1)() rgsa[0].cElements = len(value) rgsa[0].lBound = 0 pa = _safearray.SafeArrayCreateEx(vartype, 1, rgsa, None) pa = cast(pa, cls) # Now, fill the data in: ptr = POINTER(itemtype)() # pointer to the item values _safearray.SafeArrayAccessData(pa, byref(ptr)) try: for i, a in enumerate(value): ptr[i] = a finally: _safearray.SafeArrayUnaccessData(pa) var = tagVARIANT() memmove(byref(var._), byref(pa), sizeof(pa)) var.vt = VT_ARRAY | pa._vartype_ return var
def create_from_linearized_matrix(value): from ctypes import (POINTER, Structure, byref, cast, c_long, c_float, c_double, memmove, pointer, sizeof) from comtypes import _safearray, IUnknown, com_interface_registry from comtypes.automation import VARIANT, VT_R8, VT_ARRAY, tagVARIANT from comtypes.safearray import _midlSAFEARRAY addr, n = value.buffer_info() vartype = VT_R8 itemtype = c_double cls = _midlSAFEARRAY(itemtype) matrixsize = 4 rgsa = (_safearray.SAFEARRAYBOUND * 2)() rgsa[0].cElements = matrixsize rgsa[0].lBound = 0 rgsa[1].cElements = matrixsize rgsa[1].lBound = 0 pa = _safearray.SafeArrayCreateEx(vartype, 2, rgsa, None) pa = cast(pa, cls) # Now, fill the data in: ptr = POINTER(itemtype)() # pointer to the item values _safearray.SafeArrayAccessData(pa, byref(ptr)) try: nbytes = matrixsize**2 * sizeof(itemtype) memmove(ptr, addr, nbytes) finally: _safearray.SafeArrayUnaccessData(pa) var = tagVARIANT() memmove(byref(var._), byref(pa), sizeof(pa)) var.vt = VT_ARRAY | pa._vartype_ return var
def test(self): # The point of this test is the ReadWaveform method below, # which takes several [in, out] arguments. agDrvr = CreateObject("Agilent546XX.Agilent546XX") # XXX XXX XXX The following call crashes hard with an accessviolation when # the OANOCACHE environ variable is set. import os if "OANOCACHE" in os.environ: print "Cannot test. buggy COM object?" return # Initialize the driver in simulation mode. Resource descriptor is ignored. agDrvr.Initialize("", False, False, "Simulate=true") # Initialize driver. Edit resource descriptor for your system. # agDrvr.Initialize("GPIB0::7::INSTR", False, False, "QueryInstrStatus=true") from comtypes.gen import IviScopeLib iviDrvr = agDrvr.QueryInterface(IviScopeLib.IIviScope) # Get driver Identity properties. Driver initialization not required. ## print "Identifier:", iviDrvr.Identity.Identifier ## print " Revision:", agDrvr.Identity.Revision ## print "Description:", agDrvr.Identity.Description # Get instrument Identity properties. ## print "InstrumentModel: ", agDrvr.Identity.InstrumentModel ## print " FirmwareRevision: ", agDrvr.Identity.InstrumentFirmwareRevision ## print " SerialNumber: ", agDrvr.System.SerialNumber # Setup for a measurement. Reset in this case. agDrvr.Utility.Reset() pMeasurement = agDrvr.Measurements.Item("UserChannel1") # ReadWaveform() takes a sweep and reads the data. # # Definition generated for ReadWaveform(): #COMMETHOD([helpstring(u'Acquires and returns a waveform on the configured channels.')], # HRESULT, 'ReadWaveform', # ( ['in'], Agilent546XXTimeOutEnum, 'MaxTime' ), # ( ['in', 'out'], POINTER(_midlSAFEARRAY(c_double)), 'pWaveformArray' ), # ( ['in', 'out'], POINTER(c_double), 'pInitialX' ), # ( ['in', 'out'], POINTER(c_double), 'pXIncrement' )), # [in, out] arguments are now optional (comtypes # constructs an empty default value when nothing is # passed). psaWaveform = _midlSAFEARRAY(c_double).create([]) self._check_result(pMeasurement.ReadWaveform(20000)) self._check_result(pMeasurement.ReadWaveform(20000, pInitialX=9.0)) self._check_result(pMeasurement.ReadWaveform(20000, pXIncrement=9.0, pInitialX=3.0)) self._check_result(pMeasurement.ReadWaveform(20000)) self._check_result(pMeasurement.ReadWaveform(20000, [])) self._check_result(pMeasurement.ReadWaveform(20000, pWaveformArray = [])) self._check_result(pMeasurement.ReadWaveform(20000, psaWaveform)) self._check_result(pMeasurement.ReadWaveform(20000, pXIncrement=9.0))
class ISetupInstance2(ISetupInstance): _iid_ = GUID('{89143C9A-05AF-49B0-B717-72E218A2185C}') _methods_ = [ COMMETHOD([], HRESULT, 'GetState', (['out'], POINTER(DWORD), 'pState')), COMMETHOD( [], HRESULT, 'GetPackages', (['out'], POINTER(_midlSAFEARRAY( POINTER(ISetupPackageReference))), 'ppPackage')) ]
def _get_value(self, dynamic=False): vt = self.vt if vt in (VT_EMPTY, VT_NULL): return None elif vt == VT_I1: return self._.VT_I1 elif vt == VT_I2: return self._.VT_I2 elif vt == VT_I4: return self._.VT_I4 elif vt == VT_I8: return self._.VT_I8 elif vt == VT_UI8: return self._.VT_UI8 elif vt == VT_INT: return self._.VT_INT elif vt == VT_UI1: return self._.VT_UI1 elif vt == VT_UI2: return self._.VT_UI2 elif vt == VT_UI4: return self._.VT_UI4 elif vt == VT_UINT: return self._.VT_UINT elif vt == VT_R4: return self._.VT_R4 elif vt == VT_R8: return self._.VT_R8 elif vt == VT_BOOL: return self._.VT_BOOL elif vt == VT_BSTR: return self._.bstrVal elif vt == VT_DATE: days = self._.VT_R8 return datetime.timedelta(days=days) + _com_null_date elif vt == VT_CY: return self._.VT_CY / decimal.Decimal("10000") elif vt == VT_UNKNOWN: val = self._.c_void_p if not val: # We should/could return a NULL COM pointer. # But the code generation must be able to construct one # from the __repr__ of it. return None # XXX? ptr = cast(val, POINTER(IUnknown)) # cast doesn't call AddRef (it should, imo!) ptr.AddRef() return ptr.__ctypes_from_outparam__() elif vt == VT_DECIMAL: return self.decVal.as_decimal() elif vt == VT_DISPATCH: val = self._.c_void_p if not val: # See above. return None # XXX? ptr = cast(val, POINTER(IDispatch)) # cast doesn't call AddRef (it should, imo!) ptr.AddRef() if not dynamic: return ptr.__ctypes_from_outparam__() else: from comtypes.client.dynamic import Dispatch return Dispatch(ptr) # see also c:/sf/pywin32/com/win32com/src/oleargs.cpp elif self.vt & VT_BYREF: return self elif vt == VT_RECORD: from comtypes.client import GetModule from comtypes.typeinfo import IRecordInfo # Retrieving a COM pointer from a structure field does NOT # call AddRef(), have to call it manually: punk = self._.pRecInfo punk.AddRef() ri = punk.QueryInterface(IRecordInfo) # find typelib tlib = ri.GetTypeInfo().GetContainingTypeLib()[0] # load typelib wrapper module mod = GetModule(tlib) # retrive the type and create an instance value = getattr(mod, ri.GetName())() # copy data into the instance ri.RecordCopy(self._.pvRecord, byref(value)) return value elif self.vt & VT_ARRAY: typ = _vartype_to_ctype[self.vt & ~VT_ARRAY] return cast(self._.pparray, _midlSAFEARRAY(typ)).unpack() else: raise NotImplementedError("typecode %d = 0x%x)" % (vt, vt))
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)