This is a follow up from my previous post. Read that post for context. Note that it is not strict COM interop - but the C++ interfaces are COM compatible.
Im trying to implement this C++ interface in C#
class IPluginFactory : public FUnknown
{
virtual tresult PLUGIN_API createInstance (FIDString cid, FIDString iid, void** obj) = 0;
};
My C# code looks like this:
[ComImport]
[Guid(Interfaces.IPluginFactory)]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IPluginFactory
{
[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
Int32 CreateInstance([In] ref Guid classId, [In] ref Guid interfaceId, [MarshalAs(UnmanagedType.IUnknown), In, Out] ref object instance);
}
The implementation assigns a new object instance to the 'instance' parameter and returns 0 (S_OK). I even cast to the expected (managed) interface.
instance = (IPluginBase)new PluginBase();
return 0;
The object returned is represented by this C++ interface:
class IPluginBase: public FUnknown
{
public:
virtual tresult PLUGIN_API initialize (FUnknown* context) = 0;
virtual tresult PLUGIN_API terminate () = 0;
};
Which looks like this in my C# implementation:
[ComImport]
[Guid(Interfaces.IPluginBase)]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IPluginBase
{
[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
Int32 Initialize([MarshalAs(UnmanagedType.IUnknown), In] object context);
[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
Int32 Terminate();
}
In the unmanaged C++ test application I wrote, I can successfully call createInstance and receive a non-null pointer the code uses as a IPluginBase*.
The problem comes when I try to call the 'initialize' method on this IPluginBase* pointer. It never reaches the managed code (no breakpoint is hit - other breakpoint work fine) and the return code is 0x80004003. It looks like the wrapper does some intercepting here...
My question is: is the declaration of the managed representation of CreateInstance correct? What am I missing here? (this should be plain vanilla interop, should it not?)
Other suggestions on declaration 'style' are also welcome. Thanx, Marc.
EDIT: The problem seems to lie with the createInstance method. I am unable to get the interface returned that is asked for by the iid parameter.
[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
Int32 CreateInstance([In] ref Guid classId, [In] ref Guid interfaceId, [MarshalAs(UnmanagedType.IUnknown, IidParameterIndex = 1), In, Out] ref object instance);
I have also tried UnmanagedType.Interface in combination with the IidParameterIndex but both result in a IUnknown being marshaled back. If I re-query the IPluginBase interface the IPluginBase::initialize method works (breakpoint in managed code hits).