Interop COM(-isch)接口封送会在简单调用时导致AccessViotlationException

我正在尝试为本机C ++插件标准编写托管互操作库。 此本机C ++库使用C​​OM兼容的接口设计。 但是,它不会做任何类注册的东西。 与COM一样,所有接口都派生自IUnknown(称为FUnknown,但无论如何都是相同的3种方法)。

我编写了一个简单的C ++控制台应用程序,它可以加载我的托管测试插件,并通过导出的方法检索初始(根)接口(对象工厂模式 – 与com类似)。 我使用第三方DllExport代码属性实现 – 这似乎工作正常。 C ++测试应用程序使用LoadLibrary / GetProcAddress并成功检索对该接口的引用。 我可以在托管导出函数中设置断点,并按预期命中。

然后C ++测试应用程序在IUnknown(部分)接口上调用AddRef,它返回2 – 正如预期的那样。 请注意,我的托管接口定义(counter-part)不是从IUnknown派生的 – 或者包含这些方法。 我想说这意味着托管编组魔法已经介入并提供了CCW。

然后C ++测试应用程序调用工厂接口上的一个简单方法 – 一个只返回一个int32 – 并且也到达托管实现(断点被命中),但是当该方法返回时抛出一个AccessViolationException – 在托管中的某处 – 无管理的过渡。

class IPluginFactory : public FUnknown { public: // removed other methods before and after this one virtual int32 PLUGIN_API countClasses () = 0; }; 

int32是#define,PLUGIN_API被定义为__stdcall – 据我所知,这是COM兼容的。

我定义的接口的托管表示如下:

 [ComImport] [Guid("same guid as in C++ file")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IPluginFactory { [return: MarshalAs(UnmanagedType.I4)] Int32 CountClasses(); } 

此方法的托管实现只返回一个硬编码的数字(1)。

我尝试了很多东西(很多我甚至都记不起来了),目前我不知道如何解决这个问题,或者问题是什么。

任何帮助深表感谢。 感谢名单!

编辑:要求获得有关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; }; 

我们看不到FUnknown的样子。 它必须与IUnknown相同才能使interop工作。 CLR将自动调用AddRef,Release和QueryInterface。 并且非常重要的是,FUnknown中只有三个方法,如果FUnknown或多或少,那么当C#代码调用CountClasses()时,你最终会调用完全错误的方法。 确实是触发AVE的好方法。

我们可以看到的一个问题是CountClasses不兼容COM,方法必须返回一个HRESULT的Int32。 错误代码(非零值)会自动触发C#程序中的exception。 支持不兼容的方法签名,您必须使用属性。 像这样:

 [PreserveSig] int CountClasses(); 

否则这个错误不足以解释AVE。 界面不匹配是你更有可能的克星。 在这种情况下,您需要一个C ++ / CLI包装器。