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.macint...@acma.gov.au<mailto:andrew.macint...@acma.gov.au>        
    http://www.acma.gov.au/

From: python-win32 
[mailto:python-win32-bounces+andrew.macintyre=acma.gov...@python.org] On Behalf 
Of Peter Enenkel
Sent: Tuesday, 21 February 2017 6:46 AM
To: Tim Roberts
Cc: python-win32@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 <t...@probo.com<mailto:t...@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, t...@probo.com<mailto:t...@probo.com>
Providenza & Boekelheide, Inc.

_______________________________________________
python-win32 mailing list
python-win32@python.org<mailto:python-win32@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.
_______________________________________________
python-win32 mailing list
python-win32@python.org
https://mail.python.org/mailman/listinfo/python-win32

Reply via email to