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 create_from_ndarray(cls, value, extra, lBound=0): from comtypes.automation import VARIANT #c:/python25/lib/site-packages/numpy/ctypeslib.py numpy = __import__("numpy.ctypeslib") # If processing VARIANT, makes sure the array type is correct. if cls._itemtype_ is VARIANT: if value.dtype != npsupport.VARIANT_dtype: value = _ndarray_to_variant_array(value) else: ai = value.__array_interface__ if ai["version"] != 3: raise TypeError( "only __array_interface__ version 3 supported") if cls._itemtype_ != numpy.ctypeslib._typecodes[ai["typestr"]]: raise TypeError("Wrong array item type") # SAFEARRAYs have Fortran order; convert the numpy array if needed if not value.flags.f_contiguous: value = numpy.array(value, order="F") # For VT_UNKNOWN or VT_DISPATCH, extra must be a pointer to # the GUID of the interface. # # For VT_RECORD, extra must be a pointer to an IRecordInfo # describing the record. rgsa = (_safearray.SAFEARRAYBOUND * value.ndim)() nitems = 1 for i, d in enumerate(value.shape): nitems *= d rgsa[i].cElements = d rgsa[i].lBound = lBound pa = _safearray.SafeArrayCreateEx( cls._vartype_, value.ndim, # cDims rgsa, # rgsaBound extra) # pvExtra if not pa: if cls._vartype_ == VT_RECORD and extra is None: raise TypeError( "Cannot create SAFEARRAY type VT_RECORD without IRecordInfo." ) # Hm, there may be other reasons why the creation fails... raise MemoryError() # We now have a POINTER(tagSAFEARRAY) instance which we must cast # to the correct type: pa = cast(pa, cls) # Now, fill the data in: ptr = POINTER(cls._itemtype_)() # pointer to the item values _safearray.SafeArrayAccessData(pa, byref(ptr)) try: nbytes = nitems * sizeof(cls._itemtype_) memmove(ptr, value.ctypes.data, nbytes) finally: _safearray.SafeArrayUnaccessData(pa) return pa
def set_variant_matrix(self, value): if not self.is_nested_iterable(value): raise TypeError('Input data is not nested list/tuple.') if self.is_ragged(value): raise TypeError('Input data should not be a ragged array.') num_row = len(value) num_col = len(value[0]) variant = VARIANT() _VariantClear(variant) # Clear the original data rgsa = (_safearray.SAFEARRAYBOUND * 2)() rgsa[0].cElements = num_row rgsa[0].lBound = 0 rgsa[1].cElements = num_col rgsa[1].lBound = 0 pa = _safearray.SafeArrayCreateEx( VT_VARIANT, 2, rgsa, # rgsaBound None) # pvExtra if not pa: raise MemoryError() ptr = POINTER(VARIANT)() # container for the values _safearray.SafeArrayAccessData(pa, byref(ptr)) try: # I have no idea why 2D safearray is column-major. index = 0 for n in range(num_col): for m in range(num_row): ptr[index] = value[m][n] index += 1 finally: _safearray.SafeArrayUnaccessData(pa) memmove(byref(variant._), byref(pa), sizeof(pa)) variant.vt = VT_ARRAY | VT_VARIANT return variant