[python-win32] passing array by reference (3) [SEC=UNCLASSIFIED]

Andrew MacIntyre Andrew.MacIntyre at acma.gov.au
Mon Feb 20 18:33:53 EST 2017


If you’re prepared to consider another approach, comtypes (https://pypi.python.org/pypi/comtypes) can generate module definitions from TLB files.  Comtypes supports passing by reference via the underlying ctypes FFI.

Andrew.

-------------------------> "These thoughts are mine alone!" <---------
Andrew MacIntyre           Operations, Services and Technologies Branch
tel:   +61 2 6219 5356     Communications Infrastructure Division
                           Australian Communications & Media Authority
email: andrew.macintyre at acma.gov.au<mailto:andrew.macintyre at acma.gov.au>            http://www.acma.gov.au/

From: python-win32 [mailto:python-win32-bounces+andrew.macintyre=acma.gov.au at python.org] On Behalf Of Peter Enenkel
Sent: Tuesday, 21 February 2017 6:46 AM
To: Tim Roberts
Cc: python-win32 at python.org
Subject: Re: [python-win32] passing array by reference (3)

Hello Tim,
I concur that the array SHOULD be a return value (at the very least in Python). Unfortunately it isn't. Definitely not with late binding and I think not with early binding. The function does expect a parameter of the described type and does not return anything.
In my opinion it would theoretically be possible to process an argument by reference in Python, of cause it would have to be a mutable object. Which, as you mentioned, tuples are not, so it would have to be restricted to lists or some specialized transport object. Admittedly, any such solution would not be particularly pythonic. I thought that the pythoncom.VARIANT class is such a transport object. But I could not get it to work.
I suspect that you are correct that the interface might not be declared properly on the serverside. On the other hand similar problems with passing arrays by reference seem to have cropped up with other COM servers also.
I have access to the official Catia V5 automation IDL documentation (which is reasonably complete) as well as the .tlb files. But I do not know what I could do with the later.

Unfortunately Catia has deemed it necessary to split the COM server into several (more that two dozen) files which doesn't exactly help with early binding and identifying the required interfaces. That is probably one of the reasons I could not get it to work with early binding. An other difficulty with that is, that (interface) inheritance is used, i.e. both PartDocument and ProductDocument both inherit from Document but each has additional attributes. Functions always seem to return the base type which then would require some kind of cast.
I have managed to implement a workaround in the manner that Andreas Holtz suggested. That is, using win32com to instruct Catia to execute a VBScript function which calls GetComponents with an ByRef argument and then returns it as a return value, which in turn is passed back to python. Not a particularly elegant solution, but it works! So the pressure to find a "native" solution isn't quite as high as before. Nevertheless I'm still interested in a way to do it "right". If you have any ideas in that direction I'd appreciate hearing them.
best regards
Peter



2017-02-20 19:07 GMT+01:00 Tim Roberts <timr at probo.com<mailto:timr at probo.com>>:
Peter Enenkel wrote:
>
> I'm trying to read some data from CATIA v5 (which is an older CAD
> application) via its COM server. Overall it works rather well, even if
> I'm fairly new to COM communication.
>
> Nevertheless I have run into a problem: One specific function
> *GetComponents * is supposed to return its results via an array passed
> by reference. As far as I can tell it is exactly the same problem as
> in
> (1)https://mail.python.org/pipermail/python-win32/2002-November/000562.html
> and
> (2)https://mail.python.org/pipermail/python-win32/2014-July/013234.html
> unfortunately there doesn't appear to be a solution as of yet.
>
> The python call looks something like this
> a = list(range(0,12))
> b = catapp.ActiveProduct.Position.GetComponents(a)
> print(a) # outputs (0,1,2,3,4,5,6,7,8,9,10,11) instead of the actual
> values

Usually, in this kind of situation, the array would be an output parameter:

    b, a = catapp.ActiveProduct.Position.GetComponents()

Remember that Python doesn't actually do pass-by-reference in the way
you are used to.  In your code above, you aren't really passing "a".
What you're passing is the list that "a" is bound to.  The Python COM
code converts that into whatever type the function wants.  If that array
gets changed, it doesn't change the list.  It can't, because that
parameter might actually have been a tuple, which can't be modified, and
there is no way for the function to change the binding of "a".  That's
why the COM stuff usually returns the changed parameter, so you can
change your binding.

Do you have the actual function signature in C++ or IDL form?  If they
haven't declared it properly, PythonCOM might not be able to determine
that this is an output parameter.

--
Tim Roberts, timr at probo.com<mailto:timr at probo.com>
Providenza & Boekelheide, Inc.

_______________________________________________
python-win32 mailing list
python-win32 at python.org<mailto:python-win32 at python.org>
https://mail.python.org/mailman/listinfo/python-win32


NOTICE: This email message is for the sole use of the intended recipient(s) 
 and may contain confidential and privileged information. Any unauthorized 
 review, use, disclosure or distribution is prohibited. If you are not the 
 intended recipient, please contact the sender by reply email and destroy all 
 copies of the original message.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-win32/attachments/20170220/755d316c/attachment.html>


More information about the python-win32 mailing list