Interop COM(-isch)接口封送结果在AccessViotlationException上进行简单调用 [英] Interop COM(-isch) interface marshaling results in AccessViotlationException on simple call

查看:184
本文介绍了Interop COM(-isch)接口封送结果在AccessViotlationException上进行简单调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图为本地C ++插件标准编写托管互操作库。这个本地C ++库使用C​​OM兼容的接口设计。然而,它不是,做任何类注册的东西。与COM一样,所有接口派生自IUnknown(称为FUnknown,但仍然有相同的3个方法)。

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).

我写了一个简单的C ++控制台应用程序加载我的托管测试插件和检索通过导出的方法初始(根)接口(对象工厂模式 - 很像com)。我使用第三方DllExport代码属性实现 - 似乎工作正常。 C ++测试应用程序使用LoadLibrary / GetProcAddress并成功检索对接口的引用。

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.

然后,C ++测试应用程序在IUnknown(部分)接口上调用AddRef,返回2 - 可以预期。注意,我的托管接口定义(counter-part)不是从IUnknown派生 - 或包括这些方法。

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.

然后,C ++测试应用程序在工厂界面上调用一个简单的方法 - 一个只是简单的方法返回一个int32 - 并且也到达托管实现(断点获取命中),但是该方法返回它抛出一个AccessViolationException - 在托管非托管转换中的某个地方。

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;       
};

int32是一个#define,PLUGIN_API定义为__stdcall - COM兼容我可以告诉。

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();
}

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

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.

任何帮助都非常感谢。 Thanx!

Any help is much appreciated. Thanx!

编辑:请求FUnknown的详细信息:

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;
};


推荐答案

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

We can't see what FUnknown looks like. It must be identical to IUnknown to allow the interop to work. The CLR will make calls to AddRef, Release and QueryInterface automatically. And it is very important that there are exactly three methods in FUnknown, if FUnknown has more or less then you'll end up calling the complete wrong method when your C# code calls CountClasses(). Indeed a good way to trigger an AVE.

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

One problem that we can see is that CountClasses is not COM compatible, methods must return an Int32 that is the HRESULT. An error code, a value that isn't zero automatically triggers an exception in the C# program. Incompatible method signatures are supported, you have to use an attribute. Like this:

[PreserveSig]
int CountClasses();

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

This mistake is otherwise not sufficient to explain the AVE. An interface mismatch is your likelier nemesis. In which case you need a C++/CLI wrapper.

这篇关于Interop COM(-isch)接口封送结果在AccessViotlationException上进行简单调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆