Great !

Thank you very much for this patch Thomas !

I can confirm that the patch works as expected, I have applied it to my
dynamic.py file.

For everyone planing to use python to control Rhinoceros scripting interface
by using provided com object, I would suggest you to use comtypes instead of
pywin32.  The difference is that comtypes can pass 1D safearray, thus making
possible drawing of NURBS curve in Rhino provided that the coordinates of
control points are previously available. For example :

from comtypes.client import CreateObject

R = CreateObject("Rhino4.Application")
RS = R.GetScriptObject
RS._FlagAsMethod("AddPoint", "AddCurve") # Here you specify the functions
you gonna use. This works after applying current patch. This patch enables
you to use all functions as
RS.RS.AddCurve([[54,3.0],[2,34,0],[23,45,0]]) # set of NURBS control point

Once again thank you Thomas, well done!
I was trying to implement similar patch but got lost in the code.

Cheers,
Alkin

On 31 March 2010 21:31, Thomas Heller <thel...@ctypes.org> wrote:

> А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&#174; 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
> comtypes-users@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/comtypes-users
>
------------------------------------------------------------------------------
Download Intel&#174; 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
comtypes-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/comtypes-users

Reply via email to