コード例 #1
0
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
コード例 #2
0
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
コード例 #3
0
        def _get_elements_raw(self, num_elements):
            """Returns a flat list or ndarray containing ALL elements in
            the safearray."""
            from comtypes.automation import VARIANT
            # XXX Not sure this is true:
            # For VT_UNKNOWN and VT_DISPATCH, we should retrieve the
            # interface iid by SafeArrayGetIID().
            ptr = POINTER(self._itemtype_)()  # container for the values
            _safearray.SafeArrayAccessData(self, byref(ptr))
            try:
                if self._itemtype_ == VARIANT:
                    # We have to loop over each item, so we get no
                    # speedup by creating an ndarray here.
                    return [i.value for i in ptr[:num_elements]]
                elif issubclass(self._itemtype_, POINTER(IUnknown)):
                    iid = _safearray.SafeArrayGetIID(self)
                    itf = com_interface_registry[str(iid)]
                    # COM interface pointers retrieved from array
                    # must be AddRef()'d if non-NULL.
                    elems = ptr[:num_elements]
                    result = []
                    # We have to loop over each item, so we get no
                    # speedup by creating an ndarray here.
                    for p in elems:
                        if bool(p):
                            p.AddRef()
                            result.append(p.QueryInterface(itf))
                        else:
                            # return a NULL-interface pointer.
                            result.append(POINTER(itf)())
                    return result
                else:
                    # If the safearray element are NOT native python
                    # objects, the containing safearray must be kept
                    # alive until all the elements are destroyed.
                    if not issubclass(self._itemtype_, Structure):
                        # Create an ndarray if requested. This is where
                        # we can get the most speed-up.
                        # XXX Only try to convert types known to
                        #     numpy.ctypeslib.
                        if (safearray_as_ndarray and self._itemtype_ in
                                numpy.ctypeslib._typecodes.values()):
                            arr = numpy.ctypeslib.as_array(ptr,
                                                           (num_elements,))
                            return arr.copy()
                        return ptr[:num_elements]

                    def keep_safearray(v):
                        # Simply keeping a reference to self does not keep the
                        # internal addresses of BSTR safe and strings will be
                        # overwritten. A copy of the bytes solves the problem
                        v1 = v.__class__()
                        memmove(byref(v1), byref(v), sizeof(v))
                        return v1

                    return [keep_safearray(x) for x in ptr[:num_elements]]
            finally:
                _safearray.SafeArrayUnaccessData(self)
コード例 #4
0
ファイル: safearray.py プロジェクト: pvagner/backends
        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
コード例 #5
0
        def create(cls, value, extra=None):
            """Create a POINTER(SAFEARRAY_...) instance of the correct
            type; value is an object containing the items to store.

            Python lists, tuples, and array.array instances containing
            compatible item types can be passed to create
            one-dimensional arrays.  To create multidimensional arrys,
            numpy arrays must be passed.
            """

            if "numpy" in sys.modules:
                numpy = sys.modules["numpy"]
                if isinstance(value, numpy.ndarray):
                    return cls.create_from_ndarray(value, extra)

            # 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.

            # XXX How to specify the lbound (3. parameter to CreateVectorEx)?
            # XXX How to write tests for lbound != 0?
            pa = _safearray.SafeArrayCreateVectorEx(cls._vartype_, 0,
                                                    len(value), extra)
            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_)()  # container for the values
            _safearray.SafeArrayAccessData(pa, byref(ptr))
            try:
                if isinstance(value, array.array):
                    addr, n = value.buffer_info()
                    nbytes = len(value) * sizeof(cls._itemtype_)
                    memmove(ptr, addr, nbytes)
                else:
                    for index, item in enumerate(value):
                        ptr[index] = item
            finally:
                _safearray.SafeArrayUnaccessData(pa)
            return pa
コード例 #6
0
 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
コード例 #7
0
        def _get_elements_raw(self, num_elements):
            """Returns a flat list containing ALL elements in the safearray."""
            from comtypes.automation import VARIANT
            # XXX Not sure this is true:
            # For VT_UNKNOWN and VT_DISPATCH, we should retrieve the
            # interface iid by SafeArrayGetIID().
            ptr = POINTER(self._itemtype_)()  # container for the values
            _safearray.SafeArrayAccessData(self, byref(ptr))
            try:
                if self._itemtype_ == VARIANT:
                    return [i.value for i in ptr[:num_elements]]
                elif issubclass(self._itemtype_, POINTER(IUnknown)):
                    iid = _safearray.SafeArrayGetIID(self)
                    itf = com_interface_registry[str(iid)]
                    # COM interface pointers retrieved from array
                    # must be AddRef()'d if non-NULL.
                    elems = ptr[:num_elements]
                    result = []
                    for p in elems:
                        if bool(p):
                            p.AddRef()
                            result.append(p.QueryInterface(itf))
                        else:
                            # return a NULL-interface pointer.
                            result.append(POINTER(itf)())
                    return result
                else:
                    # If the safearray element are NOT native python
                    # objects, the containing safearray must be kept
                    # alive until all the elements are destroyed.
                    if not issubclass(self._itemtype_, Structure):
                        # Creating and returning numpy arrays instead
                        # of Python tuple from a safearray is a lot faster,
                        # but only for large arrays because of a certain overhead.
                        # Also, for backwards compatibility, some clients expect
                        # a Python tuple - so there should be a way to select
                        # what should be returned.  How could that work?
                        ##                        # A hack which would return numpy arrays
                        ##                        # instead of Python lists.  To be effective,
                        ##                        # the result must not converted into a tuple
                        ##                        # in the caller so there must be changes as
                        ##                        # well!
                        ##
                        ##                        # Crude hack to create and attach an
                        ##                        # __array_interface__ property to the
                        ##                        # pointer instance
                        ##                        array_type = ptr._type_ * num_elements
                        ##                        if not hasattr(array_type, "__array_interface__"):
                        ##                            import numpy.ctypeslib
                        ##                            numpy.ctypeslib.prep_array(array_type)
                        ##                        # use the array_type's __array_interface__, ...
                        ##                        aif = array_type.__array_interface__.__get__(ptr)
                        ##                        # overwrite the 'data' member so that it points to the
                        ##                        # address we want to use
                        ##                        aif["data"] = (cast(ptr, c_void_p).value, False)
                        ##                        ptr.__array_interface__ = aif
                        ##                        return numpy.array(ptr, copy=True)
                        return ptr[:num_elements]

                    def keep_safearray(v):
                        v.__keepref = self
                        return v

                    return [keep_safearray(x) for x in ptr[:num_elements]]
            finally:
                _safearray.SafeArrayUnaccessData(self)