Re: [comtypes-users] Problem with AutoCAD
Kelie schrieb: Thomas Heller thel...@... writes: Anyway, you should NOT use 'cast' with COM object pointers. Last, but not least, 'cast' doesn't handle the COM reference count correctly. Please use 'QueryInterface' with them, like so: block = obj.QueryInterface(ACAD.IAcadBlockReference) Thanks Thomas. I'm getting an error using QueryInterface. C:\Python25\pythonw.exe C:\Python25\codes\autocad\temp\cast_test.py Traceback (most recent call last): File C:\Python25\codes\autocad\temp\cast_test.py, line 9, in module block = obj.QueryInterface(ACAD.IAcadBlockReference) File C:\Python25\Lib\site-packages\comtypes\__init__.py, line 1069, in QueryInterface self.__com_QueryInterface(byref(iid), byref(p)) _ctypes.COMError: (-2147467262, 'No such interface supported', (None, None, None, 0, None)) I guess this means, well, that the interface is not supported. BTW: Sometimes, interfaces ARE supported by COM objects but cannot be marshalled across process boundaries. You also get the above error in this case. -- Thanks, Thomas -- Check out the new SourceForge.net Marketplace. It is the best place to buy or sell services for just about anything Open Source. http://p.sf.net/sfu/Xq1LFB ___ comtypes-users mailing list comtypes-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/comtypes-users
Re: [comtypes-users] Problem with AutoCAD
Kelie schrieb: Ronan, There is a cast function. But the syntax isn't much shorter. import comtypes import comtypes.gen.AutoCAD as ACAD app = comtypes.client.GetActiveObject(AutoCAD.Application) obj = app.ActiveDocument.ModelSpace(1) #Assume this obj is a block block = comtypes.cast(obj, comtypes.POINTER(ACAD.IAcadBlockReference)) # I hope this would work # block = comtypes.cast(obj, ACAD.IAcadBlockReference) print Layer name: %s % block.Layer print Color: %d % block.Color print block.InsertionPoint print block.XScaleFactor But I'm getting error when trying to access various block properties. See output below. Apparently it was OK to access the Layer and Color properties. Don't know why. Waiting for Thomas... I haven't followed this thread so I do not really know what all this is about. Anyway, you should NOT use 'cast' with COM object pointers. Last, but not least, 'cast' doesn't handle the COM reference count correctly. Please use 'QueryInterface' with them, like so: block = obj.QueryInterface(ACAD.IAcadBlockReference) Thomas -- Check out the new SourceForge.net Marketplace. It is the best place to buy or sell services for just about anything Open Source. http://p.sf.net/sfu/Xq1LFB ___ comtypes-users mailing list comtypes-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/comtypes-users
Re: [comtypes-users] Problem with AutoCAD
Ronan Paixão schrieb: Also, I'm had some problems with type coercion. In the VB examples, the variable types are declared before using, which coerce return types. The comtypes documentation is terrible and I didn't find anything to do similar. The problem is that ms.Item(number), where ms is the ModelSpace, returns an IAcadEntity object, but sometimes I need methods from the main class (or pointer), like IACadBlockReference. Since I didn't find how to do it, I dug deep and found a way to do it like this: item=comtypes.POINTER(comtypes.gen.AutoCAD.IAcadBlockReference).from_param(ms.Item(number)) That seems a bit long, just to use the Explode() function, which is available for IACadBlockReference objects but not IACadEntity ones. Is there a more direct way to do it? See my other post in this thread: Use a QueryInterface() call. By the way, I wonder why we must enter array.array('d', coords) when a function requires an array of doubles, but when something should output an array of doubles, comtypes gives a tuple. IIRC, this is because autocad's type library isn't precise in what acad accepts. I have no idea how VB does it. Thomas -- Check out the new SourceForge.net Marketplace. It is the best place to buy or sell services for just about anything Open Source. http://p.sf.net/sfu/Xq1LFB ___ comtypes-users mailing list comtypes-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/comtypes-users
Re: [comtypes-users] Problem with AutoCAD
Thomas Heller thel...@... writes: Anyway, you should NOT use 'cast' with COM object pointers. Last, but not least, 'cast' doesn't handle the COM reference count correctly. Please use 'QueryInterface' with them, like so: block = obj.QueryInterface(ACAD.IAcadBlockReference) Thanks Thomas. I'm getting an error using QueryInterface. C:\Python25\pythonw.exe C:\Python25\codes\autocad\temp\cast_test.py Traceback (most recent call last): File C:\Python25\codes\autocad\temp\cast_test.py, line 9, in module block = obj.QueryInterface(ACAD.IAcadBlockReference) File C:\Python25\Lib\site-packages\comtypes\__init__.py, line 1069, in QueryInterface self.__com_QueryInterface(byref(iid), byref(p)) _ctypes.COMError: (-2147467262, 'No such interface supported', (None, None, None, 0, None)) This is what I got from shell: import comtypes.gen.AutoCAD as ACAD ACAD.IAcadBlockReference class 'comtypes.gen._851A4561_F4EC_4631_9B0C_E7DC407512C9_0_1_0.IAcadBlockReference' -- Check out the new SourceForge.net Marketplace. It is the best place to buy or sell services for just about anything Open Source. http://p.sf.net/sfu/Xq1LFB ___ comtypes-users mailing list comtypes-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/comtypes-users
Re: [comtypes-users] Problem with AutoCAD
Thanks a lot for your help! It certainly was crucial to kickstart my script. Specially since I didn't know I could send Lisp commands with SendCommand(). Here's what I'm doing: Em Seg, 2009-01-05 às 10:15 +, Kelie escreveu: Ronan, Thanks for taking time to explain what you're after. Here is an ugly way of achieving what you're trying to do. If you know AutoLisp/VisualLisp, this would be quite easy to follow. I'm not aware that there is a COM/ActiveX function equivalent to the ssgetfirst function. HTH. I'm not using ssgetfirst, since that would require the user to already have the correct object selected before invoking the script. I'm using doc.Utility.GetEntity(), which prompts the user to select an object. The only problem with it is that the command box keeps displaying Command: between my calls (and those are not SendCommand calls). A related problem is that with doc.Utility.GetDistance() the prompt is the second argument and I don't know how to pass the first argument as it's optional and unwanted in my case. import comtypes.client app = comtypes.client.GetActiveObject(AutoCAD.Application) doc = app.ActiveDocument #This assumes user has picked/selected ONE object to measure cmd1 = '(setq enamePicked (ssname (cadr (ssgetfirst)) 0)) ' doc.SendCommand(cmd1) #Start the MEASURE command. Add the rest of the command as you wish. The thing is that when I use GetEntity() I obtain a Python COM object, not something I can use with a lisp command, so now I'm converting from one to the other with a function which calls doc.SendCommand('(setq %s (handent %s)) ' % (name_string, python_objec.Handle) ) cmd2 = '(command MEASURE enamePicked) ' and use cmd = '(command MEASURE name_string block block_name Y % f) ' % dist_from_GetDistance doc.SendCommand(cmd2) #clean the variable after done with the MEASUREMENT command cmd3 = '(setq enamePicked nil) ' doc.SendCommand(cmd3) So, is there an easier way to convert variables from python to lisp, without using SendCommand() ? Also, I'm had some problems with type coercion. In the VB examples, the variable types are declared before using, which coerce return types. The comtypes documentation is terrible and I didn't find anything to do similar. The problem is that ms.Item(number), where ms is the ModelSpace, returns an IAcadEntity object, but sometimes I need methods from the main class (or pointer), like IACadBlockReference. Since I didn't find how to do it, I dug deep and found a way to do it like this: item=comtypes.POINTER(comtypes.gen.AutoCAD.IAcadBlockReference).from_param(ms.Item(number)) That seems a bit long, just to use the Explode() function, which is available for IACadBlockReference objects but not IACadEntity ones. Is there a more direct way to do it? By the way, I wonder why we must enter array.array('d', coords) when a function requires an array of doubles, but when something should output an array of doubles, comtypes gives a tuple. Thanks a lot, Ronan -- Check out the new SourceForge.net Marketplace. It is the best place to buy or sell services for just about anything Open Source. http://p.sf.net/sfu/Xq1LFB ___ comtypes-users mailing list comtypes-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/comtypes-users
Re: [comtypes-users] Problem with AutoCAD
Ronan, There is a cast function. But the syntax isn't much shorter. import comtypes import comtypes.gen.AutoCAD as ACAD app = comtypes.client.GetActiveObject(AutoCAD.Application) obj = app.ActiveDocument.ModelSpace(1) #Assume this obj is a block block = comtypes.cast(obj, comtypes.POINTER(ACAD.IAcadBlockReference)) # I hope this would work # block = comtypes.cast(obj, ACAD.IAcadBlockReference) print Layer name: %s % block.Layer print Color: %d % block.Color print block.InsertionPoint print block.XScaleFactor But I'm getting error when trying to access various block properties. See output below. Apparently it was OK to access the Layer and Color properties. Don't know why. Waiting for Thomas... Thanks. C:\Python25\pythonw.exe C:\Python25\codes\autocad\temp\cast_test.py Layer name: 0 Color: 256 Traceback (most recent call last): File C:\Python25\codes\autocad\temp\cast_test.py, line 12, in module print block.InsertionPoint WindowsError: exception: access violation reading 0x -- Check out the new SourceForge.net Marketplace. It is the best place to buy or sell services for just about anything Open Source. http://p.sf.net/sfu/Xq1LFB ___ comtypes-users mailing list comtypes-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/comtypes-users
Re: [comtypes-users] Problem with AutoCAD
Ronan, Thanks for taking time to explain what you're after. Here is an ugly way of achieving what you're trying to do. If you know AutoLisp/VisualLisp, this would be quite easy to follow. I'm not aware that there is a COM/ActiveX function equivalent to the ssgetfirst function. HTH. import comtypes.client app = comtypes.client.GetActiveObject(AutoCAD.Application) doc = app.ActiveDocument #This assumes user has picked/selected ONE object to measure cmd1 = '(setq enamePicked (ssname (cadr (ssgetfirst)) 0)) ' doc.SendCommand(cmd1) #Start the MEASURE command. Add the rest of the command as you wish. cmd2 = '(command MEASURE enamePicked) ' doc.SendCommand(cmd2) #clean the variable after done with the MEASUREMENT command cmd3 = '(setq enamePicked nil) ' doc.SendCommand(cmd3) -- ___ comtypes-users mailing list comtypes-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/comtypes-users
Re: [comtypes-users] Problem with AutoCAD
Ronan, I'm not sure what the answer is to your question. But I'm curious why you're trying to use Python to execute the measure command. Do you know any AutoLisp/VisualLisp or VBA? Both of them would be much easier to use in this case. What I'm finding is Python (win32com or comtypes) has its usage in automating AutoCAD, but in a (very) limited way, due to the much slower speed than AutoLisp/VisualLisp and VBA, let alone other .NET languages. I mentioned the speed issue in one of the earlier thread and my understanding is there isn't much to be done due to the out-of-process COM access nature. -- ___ comtypes-users mailing list comtypes-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/comtypes-users