Аlkin Nasuf schrieb:
> Hi Thomas,
>
> First of all thank you for the response, I really need to get around this
> issue.
>
> The com object, I am dispatching, is provided by Rhinoceros CAD package. The
> evaluation version of Rhinoceros can be obtained from here -
> http://download.rhino3d.com/rhino/4.0/evaluation/download/
> . The evaluation is quite liberal, since you can use it as much as you like,
> but you are restricted to 15 saves only.
>
> I am using this object to control VB functions provided by Rhino scripting
> interface.
>
> You can reproduce the problem by:
>
> 1. R = CreateObject("Rhino4.Application")
> 2. RS = R.GetScriptObject
> 3. RS.AddPoint([10.0,10.0,10.0])
>
> At this point I should obtain all functions provided by RhinoScript type
> library as methods, but all I get are attributes e.g.
>
>>>> RS.AddPoint([10.0,10.0,10.0])
> Traceback (most recent call last):
> File "<stdin>", line 1, in ?
> TypeError: 'NoneType' object is not callable
>
> , where RS.AddPoint() is the function I am calling.
>
> I presume that all functions in R.GetScriptObject are flagged as attributes
> instead of methods, note that R.visible =True works. In PyWin32 I used to
> flag each attribute as methods with _FlagAsMethod(attribute name) function.
>
> I hope I was able to describe the problem as much as I can.
Very clear description, and very helpful - thanks.
This simple patch should do the trick (the docstring is stolen from win32com):
<snip>
Index: comtypes/client/dynamic.py
===================================================================
--- comtypes/client/dynamic.py (revision 572)
+++ comtypes/client/dynamic.py (working copy)
@@ -58,6 +58,7 @@
def __init__(self, comobj):
self.__dict__["_comobj"] = comobj
self.__dict__["_ids"] = {} # Tiny optimization: trying not to use
GetIDsOfNames more than once
+ self.__dict__["_methods"] = set()
def __enum(self):
e = self._comobj.Invoke(-4) # DISPID_NEWENUM
@@ -85,7 +86,23 @@
"QueryInterface is forwarded to the real com object."
return self._comobj.QueryInterface(*args)
+ def _FlagAsMethod(self, *names):
+ """Flag these attribute names as being methods.
+ Some objects do not correctly differentiate methods and
+ properties, leading to problems when calling these methods.
+
+ Specifically, trying to say: ob.SomeFunc()
+ may yield an exception "None object is not callable"
+ In this case, an attempt to fetch the *property*has worked
+ and returned None, rather than indicating it is really a method.
+ Calling: ob._FlagAsMethod("SomeFunc")
+ should then allow this to work.
+ """
+ self._methods.update(names)
+
def __getattr__(self, name):
+ if name.startswith("__") and name.endswith("__"):
+ raise AttributeError(name)
## tc =
self._comobj.GetTypeInfo(0).QueryInterface(comtypes.typeinfo.ITypeComp)
## dispid = tc.Bind(name)[1].memid
dispid = self._ids.get(name)
@@ -93,6 +110,11 @@
dispid = self._comobj.GetIDsOfNames(name)[0]
self._ids[name] = dispid
+ if name in self._methods:
+ result = MethodCaller(dispid, self)
+ self.__dict__[name] = result
+ return result
+
flags = comtypes.automation.DISPATCH_PROPERTYGET
try:
result = self._comobj.Invoke(dispid, _invkind=flags)
</snip>
If it works for you I can commit it to the repository.
--
Thanks,
Thomas
------------------------------------------------------------------------------
Download Intel® Parallel Studio Eval
Try the new software tools for yourself. Speed compiling, find bugs
proactively, and fine-tune applications for parallel performance.
See why Intel Parallel Studio got high marks during beta.
http://p.sf.net/sfu/intel-sw-dev
_______________________________________________
comtypes-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/comtypes-users