[Mono-dev] COM Interop Patch

Jon Chambers joncham at gmail.com
Wed Jul 12 17:22:53 EDT 2006

Here is another attempt at a COM Interop patch. First, all
changes/contributions are MIT X11. Now, for a brief overview ;-).

I implemented COM Interop on top of the current remoting infrastructure.
This allows for two main things. 1. Forwarding of method calls to the
underlying unmanaged COM object. 2. Casting RCW (Runtime Callable Wrappers -
the managed wrapper around the unmanaged COM object) to interfaces not
specified as implemented in metadata. This can occur if a QueryInterface for
that interface's Guid (IID) succeeds on the underlying object.

So, when a user says "MyComObj obj = new MyComObj()" the runtime creates a
ComInteropProxy and returns it's TransparentProxy. However, instead of
forwarding methods via the remoting invoke mechanism using messages, I
shortcut to a Com Interop invoke. The is a great performance boost (by a few
orders of magnitude if I recall). I first emit the invoke call, which
transitions the call from a call on the transparent proxy, into a call on
the actuall RCW.

The method implementation is done by cominterop_get_native_wrapper. This
emits a method whose signature matches the managed method. The emitted
method calls a final emitted method created by
cominterop_get_native_wrapper_adjusted. The two methods, created by
cominterop_get_native_wrapper and cominterop_get_native_wrapper_adjusted are
1-1. The adjusted method matches the unmanaged signature, and as thus can
reuse all the existing unmanaged calling functionality provided by
mono_marshal_emit_native_wrapper. The only small change to
mono_marshal_emit_native_wrapper was that the function pointer is push onto
the stack at call time, rather than when the method is emitted since the
function pointer depends on the object making the call (different objects
implementing the same interface could have different implementations, and
thus vtables, thus function pointers).

Another minor note is the internal calls added to __ComObject. This is so I
can store a hashtable of COM interfaces and later release them in the
finalizer to ensure proper reference counting. I had a Hashtable in managed
code intially but couldn't access it in my finalizer.

I also implemented a series of COM Interop related methods in the Marshal

On windows you should be able to run some basic tests. I added a few to the
cominterop.cs test file but disabled them for the moment. COM is a binary
standard and I wasn't sure what vtable layouts would be like on Solaris,
ARM, etc. (I know HP is different) and didn't want to cause regressions on
those platforms. But, on windows/linux x86/64 you can enable them and run
them. Or more excitingly you can add a reference to an interop assembly on
MS and test run real COM objects (Internet Explorer for example). The
largest thing missing right now is the marshalling of com objects. So, you
can't call any methods that have parameters/return value of COM objects.
This will be the next thing I work on.

I'm sure there are some issues, so please review and I'll fix them ASAP.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.ximian.com/pipermail/mono-devel-list/attachments/20060712/bacbfe25/attachment.html 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: cominterop.diff
Type: application/octet-stream
Size: 66656 bytes
Desc: not available
Url : http://lists.ximian.com/pipermail/mono-devel-list/attachments/20060712/bacbfe25/attachment.obj 

More information about the Mono-devel-list mailing list