I am trying to write a managed interop library for a native C++ plugin standard. This native C++ library uses a COM-compatible interface design. It does NOT however, do any of the class registration stuff. As with COM, all interfaces derive from IUnknown (called FUnknown but same 3 methods anyway).
I have written a simple C++ console app that loads my managed test plugin and retrieves the initial (root) interface (an object factory pattern - much like com) through an exported method. I use a 3rd party DllExport code attribute implementation - that does seem to work fine. The C++ test app uses LoadLibrary/GetProcAddress and successfully retrieves a reference to the interface. I can set a breakpoint in my managed exported function and it gets hit as expected.
Then the C++ test app calls AddRef on the IUnknown (part of the) interface and it returns 2 - as could be expected. Note that my managed interface definition (counter-part) does NOT derive from IUnknown -or include these methods. I would say that means that the managed marshaling magic has stepped in and provided a CCW.
Then the C++ test app calls a simple method on the factory interface - one that just returns an int32 - and that also arrives in the managed implementation (breakpoint gets hit), but as that method returns it throws an AccessViolationException - somewhere in the managed-unmanaged transition.
class IPluginFactory : public FUnknown
{
public:
// removed other methods before and after this one
virtual int32 PLUGIN_API countClasses () = 0;
};
The int32 is a #define and the PLUGIN_API gets defined as __stdcall - which is COM compatible as far as I can tell.
The managed representation of that interface I have defined as follows:
[ComImport]
[Guid("same guid as in C++ file")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IPluginFactory
{
[return: MarshalAs(UnmanagedType.I4)]
Int32 CountClasses();
}
The managed implementation of this method just returns a hard coded number (1).
I have tried many things (so many I can not even remember them all) and am currently at a loss as how to resolve this, or what the problem could be.
Any help is much appreciated. Thanx!
EDIT: Request for details on FUnknown:
class FUnknown
{
public:
virtual tresult PLUGIN_API queryInterface (const TUID iid, void** obj) = 0;
virtual uint32 PLUGIN_API addRef () = 0;
virtual uint32 PLUGIN_API release () = 0;
};