Nevermind, I was able to solve it using _midlSAFEARRAY, and am posting
my solution below in case anyone else is having similar difficulty
(since the mailing lists are indexed by search engines).


    import comtypes
    import ctypes

    class ScanData(ctypes.Structure):
        _fields_ = [('mass_width', ctypes.c_double),
                    ('mass', ctypes.c_double),
                    ('charge', ctypes.c_long),
                    ('scan', ctypes.c_long)]

    def to_struct(variant, struct):
        '''
        Convert variant array of structs to tuple of structs.

        Args:
            variant (VARIANT):      filled VARIANT
            struct (Structure):     struct with _fields_
        '''

        safe_array = comtypes.safearray._midlSAFEARRAY(struct)
        return ctypes.cast(variant._.pparray, safe_array).unpack()


    scandata = comtypes.automation.VARIANT()
    size = ctypes.c_long()
    handle.GetDataFromScan(scandata, size)
    items = to_struct(scandata, ScanData)
    print(items[0].mass_width)


Thanks for the excellent library,
Alex


On 03/24/2016 10:34 AM, Alex Huszagh wrote:
> Hi,
>
> I'm working with a well-documented, but proprietary DLL I would like to
> call from Python, meaning I have no ability to edit the DLL.
>
> The method documentation itself follows something similar to the
> following:
>
>     GetDataFromScan(long nScanNumber,
>     LPVARIANT pvarScanData,
>     LPLONG pnArraySize)
>
>
> Where pvarScanData is filled with ScanData structs of the similar format:
>
>     struct ScanData
>     {
>     double dMassWidth;
>     double dMass;
>     long nCharge;
>     long nScan;
>     };
>
> So far, to try to extract data from the DLL, I have tried using various
> parameters with comtypes.automation.VARIANT, with no success.
>
>
>     import comtypes
>     import ctypes
>
>     CLSID = '{........-....-....-....-............}'
>     handle = comtypes.client.CreateObject(CLSID)
>
>
>     scandata = comtypes.automation.VARIANT()
>     size = ctypes.c_long()
>
>     # response is 0 for success, > 0 for error
>     response = handle.GetDataFromScan(scandata, size)
>
>
> Now, this works when no data is returned, however, for size > 1, an
> error is returned and no data fills the variant. So I therefore looked
> to initialize the variant. I also tried throwing various parameters,
> such as `comtypes.automation.VARIANT(comtypes.automation.VT_ARRAY)`,
> however, the few I tried (VT_ARRAY, VT_UNKNOWN) all caused the method to
> fail (produce a response > 0) even when no data was returned.
>
> I'm wondering if there's any method to initialize the Variant with a
> method like VariantInit, and then copy the data to a numpy array using
> the comtypes safearray. Any insight would be wonderful.
>
> Thank you,
> Alex
>



-- 
Alex Huszagh
Lan Huang Laboratory
Department of Physiology and Biophysics
University of California, Irvine

------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://pubads.g.doubleclick.net/gampad/clk?id=278785351&iu=/4140
_______________________________________________
comtypes-users mailing list
comtypes-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/comtypes-users

Reply via email to