I tried to use Python.NET with COM objects, and I couldn't get it to work. The documentation says it works, so I assume either that there is a bug or that I'm doing something wrong. Background: I have a large COM library of vtbl-based interfaces, not accessible through Win32all. They can be accessed through ctypes but it's slow and there are a many cases where the autogenerated wrappers are wrong. This library ships with .NET assemblies which properly deal with those special cases, so that's why I'm interested in Python.NET. What happens is I can import the interfaces, and I can import the CoClasses, but Python.NET seems to think the CoClasses are interfaces too. So when I try to instantiate an object, it fails with a message "interface constructor requires a single argument" or something like that. Any ideas? Bruce
I tried to use Python.NET with COM objects, and I couldn't get it to work. The documentation says it works, so I assume either that there is a bug or that I'm doing something wrong.
Background: I have a large COM library of vtbl-based interfaces, not accessible through Win32all. They can be accessed through ctypes but it's slow and there are a many cases where the autogenerated wrappers are wrong. This library ships with .NET assemblies which properly deal with those special cases, so that's why I'm interested in Python.NET.
What happens is I can import the interfaces, and I can import the CoClasses, but Python.NET seems to think the CoClasses are interfaces too. So when I try to instantiate an object, it fails with a message "interface constructor requires a single argument" or something like that.
Any ideas?
Hi Bruce - unfortunately I'm not much of an expert on this ;( I've mostly tested things like MSAgent that exposed automation objects. That said, unless I've really messed up somewhere, any class that you can instantiate from C# should be able to be instantiated from Python. Have you tried using those CoClasses from a test C# program? One thing that threw me off when I first tested MSAgent was the fact that there were really 2 dlls (AgentObjects.dll, AxAgentObjects.dll), one of which had only interfaces and the other had instantiatable classes. You should be able to snoop around in the COM support dlls you've generated if you have the .NET tools around. Run ILDASM on them and try to find where the instantiatable classes are. Hope this helps, Brian Lloyd brian@zope.com V.P. Engineering 540.361.1716 Zope Corporation http://www.zope.com
That did help; I see what's going on that I missed. In the typelib, one of the CoClasses is called PropertySet, and has a default interface IPropertySet. The way this gets exposed, PropertySet shows up in .NET as an interface (approximately an alias for IPropertySet), whereas the coclass gets exposed as PropertySetClass. I guess this is necessary since, in many cases, the default interface is an unnamed dispatch or dual interface. Since PropertySet cannot be overloaded to be both the name of a coclass and the name of an interface, the suffix is appended to avoid a name collision. I think Python.NET should expose the objects by their mangled names (since that matches C#) but should also apply some syntactic sugar to allow you to instantiate them with their original names (since that matches win32com, not to mention the intent of the library authors). Bruce
I sent along a patch that does what I was talking about. As it turns out, this "does" match what C# does, i.e. I can instantiate a PropertySet from C# and it knows what to do. So this change is in keeping with your design goal. However, there are a few other problems. I will see whether I can help with these as well. 1) The Python PropertySet is exposing no methods. In ILDASM, it shows "interface PropertySet implements IPropertySet", and in C# the IPropertySet methods are available on a variable declared as PropertySet. In Python they are not. 2) The first time I try to import, it sometimes fails with an ImportError "No module named ...", but if I try again, it succeeds. It seems to have a better chance of success if I first import CLR itself. I'm not sure why that should be. Bruce
Problem 1 can also be seen on ADODB.Connection. It is not specific to COM, though: Interface ICollection inherits from IEnumerable. In C#, if I declare a variable as ICollection, I'll see GetEnumerator. In Python, if I cast to ICollection, I do not see GetEnumerator. I think this is because interface inheritence is a different animal than class inheritance. It seems to be more contractual than structural. I sent a workaround to Brian. The fix is probably not the best way of doing it, and is probably not complete, but it does seem to help. - I noticed as well that properties on interfaces don't work, e.g. I have to call get_Count() rather than just accessing the Count property. from CLR.System.Collections import Hashtable, ICollection ht = Hashtable() c = ICollection(ht) print c.Count #fails A fix for this is also sent to Brian. Bruce
I haven't seen anything further on this. If there's anything more that you need from me before these enhancements can be committed, don't hesitate to email me. Bruce
I haven't seen anything further on this. If there's anything more that you need from me before these enhancements can be committed, don't hesitate to email me.
Bruce
Hi Bruce - the only thing I need is time to do it ;) I'm hoping I will get some time this weekend to at least checkin and make unit tests for the various things in the queue. Brian Lloyd brian@zope.com V.P. Engineering 540.361.1716 Zope Corporation http://www.zope.com
participants (2)
-
Brian Lloyd
-
Bruce Dodson