Discussion:
[python-win32] Python wn32com : How to give byRef parameters in object method and then get updated values
Pascal
2015-03-05 22:22:01 UTC
Permalink
Hello,

I'm not an expert, I just want to experiment python with SolidWorks
I'm trying to use its DLL with some success, but unfortunately, with
some errors :
File "<COMObject <unknown>>", line 2, in Get5
com_error: (-2147352571, 'Type mismatch', None, 5)

I'm not sure about error comment, it's a translation because my python
is in french language.

Here is a simplified extract of code :

app = win32com.client.Dispatch('Sldworks.Application')
part = app.ActiveDoc

docext = part.Extension
custPropMgr = docext.CustomPropertyManager('ma_config')
pNames = tuple(custPropMgr.GetNames) # return array of strings

for item in pNames:
print(item) # string is well printed
var1=''
var2=''
var3=False
custPropMgr.Get5(item, False, var1, var2, var3) <== error happens
here

I tried several things but I didn't reach to pass correctly the
parameters to the Get5 method.
I think the problem is with the ByRef parameters, because I already used
many method with ByVal parameters and it works rather fine.

I tried : var1, var2, var3 = custPropMgr.Get5(item, False) as suggested
somewhere but it didn't works

this method is described as below in the solidworks API help:

Visual Basic (Declaration)

Function Get5( _
ByVal/FieldName <http://help.solidworks.com/2015/english/api/sldworksapi/solidworks.interop.sldworks%7Esolidworks.interop.sldworks.icustompropertymanager%7Eget5.html#>/ As System.String, _
ByVal/UseCached <http://help.solidworks.com/2015/english/api/sldworksapi/solidworks.interop.sldworks%7Esolidworks.interop.sldworks.icustompropertymanager%7Eget5.html#>/ As System.Boolean, _
ByRef/ValOut <http://help.solidworks.com/2015/english/api/sldworksapi/solidworks.interop.sldworks%7Esolidworks.interop.sldworks.icustompropertymanager%7Eget5.html#>/ As System.String, _
ByRef/ResolvedValOut <http://help.solidworks.com/2015/english/api/sldworksapi/solidworks.interop.sldworks%7Esolidworks.interop.sldworks.icustompropertymanager%7Eget5.html#>/ As System.String, _
ByRef/WasResolved <http://help.solidworks.com/2015/english/api/sldworksapi/solidworks.interop.sldworks%7Esolidworks.interop.sldworks.icustompropertymanager%7Eget5.html#>/ As System.Boolean _
) As System.Integer

Visual Basic (Usage)

Dim instance AsICustomPropertyManager <http://help.solidworks.com/2015/english/api/sldworksapi/SolidWorks.Interop.sldworks%7ESolidWorks.Interop.sldworks.ICustomPropertyManager.html>
Dim FieldName As System.String
Dim UseCached As System.Boolean
Dim ValOut As System.String
Dim ResolvedValOut As System.String
Dim WasResolved As System.Boolean
Dim value As System.Integer

value = instance.Get5(FieldName, UseCached, ValOut, ResolvedValOut, WasResolved)

C#

System.int Get5(
System.string/FieldName <http://help.solidworks.com/2015/english/api/sldworksapi/solidworks.interop.sldworks%7Esolidworks.interop.sldworks.icustompropertymanager%7Eget5.html#>/,
System.bool/UseCached <http://help.solidworks.com/2015/english/api/sldworksapi/solidworks.interop.sldworks%7Esolidworks.interop.sldworks.icustompropertymanager%7Eget5.html#>/,
out System.string/ValOut <http://help.solidworks.com/2015/english/api/sldworksapi/solidworks.interop.sldworks%7Esolidworks.interop.sldworks.icustompropertymanager%7Eget5.html#>/,
out System.string/ResolvedValOut <http://help.solidworks.com/2015/english/api/sldworksapi/solidworks.interop.sldworks%7Esolidworks.interop.sldworks.icustompropertymanager%7Eget5.html#>/,
out System.bool/WasResolved <http://help.solidworks.com/2015/english/api/sldworksapi/solidworks.interop.sldworks%7Esolidworks.interop.sldworks.icustompropertymanager%7Eget5.html#>/
)

C++/CLI

System.int Get5(
& System.String^/FieldName <http://help.solidworks.com/2015/english/api/sldworksapi/solidworks.interop.sldworks%7Esolidworks.interop.sldworks.icustompropertymanager%7Eget5.html#>/,
& System.bool/UseCached <http://help.solidworks.com/2015/english/api/sldworksapi/solidworks.interop.sldworks%7Esolidworks.interop.sldworks.icustompropertymanager%7Eget5.html#>/,
& [Out] System.String^/ValOut <http://help.solidworks.com/2015/english/api/sldworksapi/solidworks.interop.sldworks%7Esolidworks.interop.sldworks.icustompropertymanager%7Eget5.html#>/,
& [Out] System.String^/ResolvedValOut <http://help.solidworks.com/2015/english/api/sldworksapi/solidworks.interop.sldworks%7Esolidworks.interop.sldworks.icustompropertymanager%7Eget5.html#>/,
& [Out] System.bool/WasResolved <http://help.solidworks.com/2015/english/api/sldworksapi/solidworks.interop.sldworks%7Esolidworks.interop.sldworks.icustompropertymanager%7Eget5.html#>/
)


Thanks for your help.

Best regards.


---
L'absence de virus dans ce courrier électronique a été vérifiée par le logiciel antivirus Avast.
http://www.avast.com
Greg Antal
2015-03-06 00:49:05 UTC
Permalink
_______________________________________________
python-win32 mailing list
python-***@python.org
https://mail.python.org/mailman/listinfo/python-win32
Dennis Lee Bieber
2015-03-06 02:19:15 UTC
Permalink
Post by Pascal
print(item) # string is well printed
var1=''
var2=''
var3=False
custPropMgr.Get5(item, False, var1, var2, var3) <== error happens
here
The first thing to understand is that Python does not, technically,
have "out" parameters. Second is that strings are not mutable.

For the "output" parameters you will likely need to specify a mutable
object of some type... Unfortunately, I've never been able to make sense
out of the documentation for the win32 extensions -- lots of cross linked
entries but not a single explanation of how to use them. You may need to
create VARIANT() objects for each of those output items.

Probably easier to just use the ctypes module -- that has usable
documentation.
--
Wulfraed Dennis Lee Bieber AF6VN
***@ix.netcom.com HTTP://wlfraed.home.netcom.com/
Pascal
2015-03-07 13:50:05 UTC
Permalink
Hi,

Sorry Greg, as I was the only recipient of the message, I didn't take
care to dispatch email to full python-win32 list.

I work a few since my last email and yes, I have several questions and
comments about use of win32com through SolidWorks API.

1-/ I tried makepy and the result was the same, but with google and
patience I found a way to make my functions work.

There is for me some suprising behaviour :

e.g. :

Open a doc works as :

def openDoc(self, path, docType):
model, errors, warnings = sw.OpenDoc6(model_path, cst(docType),
swconst.constants.swOpenDocOptions_Silent, '', pythoncom.Missing,
pythoncom.Missing)
model.Visible = True
return model

while getting parameters function get5 works as :

def params(self,ipart,cfg):
ext = ipart.Extension
custPropMgr = ext.CustomPropertyManager(cfg)
pNames = tuple(custPropMgr.GetNames)
pValues = []
res=0
for item in pNames:
valOut = VARIANT(pythoncom.VT_BYREF | pythoncom.VT_BSTR,'F')
resolvedValOut = VARIANT(pythoncom.VT_BYREF |
pythoncom.VT_BSTR,'R')
wasResolved = VARIANT(pythoncom.VT_BYREF |
pythoncom.VT_BOOL, 0)
res = custPropMgr.Get5(item, False, resolvedValOut, valOut,
wasResolved )
v_wR = wasResolved.value
v_wasResolved = valOut.value
v_valOut = v_wR
v_resolvedValOut = resolvedValOut.value
pValues.append([v_valOut, v_resolvedValOut, v_wasResolved])
return pValues

In first case only byRef parameters are needed and then they are
returned as triple with the normal result in usual language (model)
In second case, if you don't give a correct typed parameter, it raise an
error : type mismatch or missing (in case of pythoncom.missing)
Moreover, it don't return as I hoped : normal_result, byref1, byref2,
byref3 = custPropMgr.Get5(...) but only normal_result =
custPropMgr.Get5(...)
and byref results returned in defined variables (made with VARIANT)
Note : returned parameters are not in the right order (seems to be in
reverse order)
not really important, except in loop, because types are not
always the same, so you must init vars in the loop!

2-/ Note : this also works without making a makepy module (very
interesting for future use because nothing special to do)

We have a kind of common experience, because my first use of Python and
solidworks (not together) happens when I worked with MSC Marc/autoforge
Non-linear finite element softwares.

Thanks for your support and your french encouragement.
______________________________________________________________
Greg wrote:

I only use SolidWorks occasionally, and I have never tried to use its
API. But, it's on my computer and I knew what to look for based on my
prior experience with a finite element pre/post processor called Femap,
so I was able to help.

If you have further questions, it is best to send them to the discussion
list rather than directly to me, even if I eventually answer them.
Everything sent to the list is archived, so other people with similar
problems may be able find answers in the archives. That's why I sent my
answer to the list, too.

Bonne chance, et bon courage.

- Greg

------------------
Gregory W. Antal
Senior Technical Advisor
ATA Engineering, Inc.
13290 Evening Creek Drive South, Suite 250
San Diego, CA 92128
www.ata-e.com

***@ata-e.com
858-480-2072 (Phone)
858-792-8932 (Fax)
------------------

Pascal wrote on 3/6/2015 12:20 AM:
Hi,

Thank you so much Greg for your quick reply.
I will try it asap.
I saw several times references to makepy but it was usually confuse for
me and I didn't understand really what is behind it.
Your explanation is very clear and I understand better its utility.

Maybe, I'm a bit curious, but you seems to know Solidworks, do you use
Python with it ?

Thanks again and have a good day.
Post by Pascal
Hello,
I'm not an expert, I just want to experiment python with SolidWorks
I'm trying to use its DLL with some success, but unfortunately, with
File "<COMObject <unknown>>", line 2, in Get5
com_error: (-2147352571, 'Type mismatch', None, 5)
I'm not sure about error comment, it's a translation because my
python is in french language.
app = win32com.client.Dispatch('Sldworks.Application')
part = app.ActiveDoc
docext = part.Extension
custPropMgr = docext.CustomPropertyManager('ma_config')
pNames = tuple(custPropMgr.GetNames) # return array of strings
print(item) # string is well printed
var1=''
var2=''
var3=False
custPropMgr.Get5(item, False, var1, var2, var3) <== error
happens here
I tried several things but I didn't reach to pass correctly the
parameters to the Get5 method.
I think the problem is with the ByRef parameters, because I already
used many method with ByVal parameters and it works rather fine.
I tried : var1, var2, var3 = custPropMgr.Get5(item, False) as
suggested somewhere but it didn't works
Visual Basic (Declaration)
Function Get5( _
ByVal/FieldName <http://help.solidworks.com/2015/english/api/sldworksapi/solidworks.interop.sldworks%7Esolidworks.interop.sldworks.icustompropertymanager%7Eget5.html#>/ As System.String, _
ByVal/UseCached <http://help.solidworks.com/2015/english/api/sldworksapi/solidworks.interop.sldworks%7Esolidworks.interop.sldworks.icustompropertymanager%7Eget5.html#>/ As System.Boolean, _
ByRef/ValOut <http://help.solidworks.com/2015/english/api/sldworksapi/solidworks.interop.sldworks%7Esolidworks.interop.sldworks.icustompropertymanager%7Eget5.html#>/ As System.String, _
ByRef/ResolvedValOut <http://help.solidworks.com/2015/english/api/sldworksapi/solidworks.interop.sldworks%7Esolidworks.interop.sldworks.icustompropertymanager%7Eget5.html#>/ As System.String, _
ByRef/WasResolved <http://help.solidworks.com/2015/english/api/sldworksapi/solidworks.interop.sldworks%7Esolidworks.interop.sldworks.icustompropertymanager%7Eget5.html#>/ As System.Boolean _
) As System.Integer
Visual Basic (Usage)
Dim instance AsICustomPropertyManager <http://help.solidworks.com/2015/english/api/sldworksapi/SolidWorks.Interop.sldworks%7ESolidWorks.Interop.sldworks.ICustomPropertyManager.html>
Dim FieldName As System.String
Dim UseCached As System.Boolean
Dim ValOut As System.String
Dim ResolvedValOut As System.String
Dim WasResolved As System.Boolean
Dim value As System.Integer
value = instance.Get5(FieldName, UseCached, ValOut, ResolvedValOut, WasResolved)
I'm not much of an expert either, but I also use an API with many
ByRef parameters in its method calls. The way I solved the problem was
to use "early binding" of the COM objects.
To do that, you must first find the Type Library for your API. For
SolidWorks, this may be "sldworks.tlb", although I can't really be
sure. I see 20 "tlb" files in my [/SolidWorks_path/]\SolidWorks
folder, and I have no idea which one you might need, or even if you
need all of them. I would start with "sldworks.tlb".
Next, from that type library, you create a Python file that you can
import into your code. You do that with the "makepy" utility that
comes with the Python COM package.
1. Open a command window in the folder where you keep the Python code
you're developing.
2. Enter the command
[/Python_path/]\Lib\site-packages\win32com\client\makepy.py -v -o
PySldworks.py [/SolidWorks_path/]\SolidWorks\sldworks.tlb
This will create a file called PySldworks.py (you can name it whatever
you want, of course). Now you can just add "Import PySldworks" to all
the Import statements you already use.
Instead of
app = win32com.client.Dispatch('Sldworks.Application')
you have something like
app = PySldworks.SldWorks
Now those calls that return data using ByRef parameters should work
with the Python-like form you tried because PySldworks.py has already
var1, var2, var3 = custPropMgr.Get5(item, False)
If that method has a return code, it will appear before the ByRef
rc, var1, var2, var3 = custPropMgr.Get5(item, False)
If that doesn't work, you can look in PySldworks.py to understand
exactly what it thinks it should do with that method; it is, after
all, just another Python file.
If there is another way to solve this problem, I don't know what it
is. One of the real experts who monitor this list will have to help
you with that.
- Greg Antal
------------------
Gregory W. Antal
Senior Technical Advisor
ATA Engineering, Inc.
13290 Evening Creek Drive South, Suite 250
San Diego, CA 92128
www.ata-e.com
858-480-2072 (Phone)
858-792-8932 (Fax)
------------------
---
L'absence de virus dans ce courrier électronique a été vérifiée par le logiciel antivirus Avast.
http://www.avast.com

Loading...