p / invoke操作最终执行另一个函数

时间:2012-08-16 05:59:21

标签: c# c++ marshalling com-interop com-interface

不确定为什么会发生这种情况,但是当我执行我的一个c#函数时,可以通过以下c#接口来定义:

[ComImport, Guid("EA5435EA-AA5C-455d-BF97-5F19DC9C29AD"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IClosedCaptionsDecoder2 
{
    [PreserveSig]
    int SetConfig([In] ref ClosedCaptionsDecoderConfig config);
    [PreserveSig]
    int GetConfig([Out] out ClosedCaptionsDecoderConfig config);
}

和c ++接口:

    interface __declspec(uuid("{EA5435EA-AA5C-455d-BF97-5F19DC9C29AD}"))
    IClosedCaptionsDecoder2 : public IClosedCaptionsDecoder
    {
        STDMETHOD(SetConfig)(IN CLOSEDCAPTIONSDECODERCONFIG& config) PURE;
        STDMETHOD(GetConfig)(OUT CLOSEDCAPTIONSDECODERCONFIG* pConfig) PURE;
    };

我被重定向到'先前'接口声明的另一个函数。 当我尝试执行以下命令时,例如: config->调用setConfig(....)。重定向到(或下一个执行命令)的函数由 IClosedCaptionsDecoder2 的基类实现,该基类称为 IClosedCaptionsDecoder

此接口的c ++ decleration为:

interface __declspec(uuid("{26B8D7F1-7DD8-4a59-9663-8D00C03135F7}"))
        IClosedCaptionsDecoder : public IUnknown
        {
            STDMETHOD(xxx)(IExternalCCObserver* pObserver, LONG lFlags) PURE;
        };

所以config-> SetConfig()实际调用config-> xxx(),我的猜测是函数的错误有问题。

我甚至试图在c#方面定义整个关系(继承等),但这也不起作用。

我将不胜感激任何帮助。 谢谢!

编辑:当我试图调用GetConfig()时,它实际上执行了SetConfig()。所以我肯定有指针偏移等问题。每个函数,在解除顺序中调用前一个函数,怎么可能?

Edit2 :我设法通过将所有函数添加到IClosedCaptionsDecoder2接口来解决此问题。

1 个答案:

答案 0 :(得分:1)

这是在CLR中实现COM互操作的方式中的缺陷的副作用。当接口派生自除IUnknown或IDispatch之外的其他接口时,它无法将接口的方法正确映射到v表槽。它将第一个方法映射到第一个可用的槽,即使它已经被具体的coclass实现中的继承接口的方法占用。不支持多重继承的副作用。所以出了什么问题,当客户端代码调用IClosedCaptionsDecoder :: xxx()时,它最终会调用IClosedCaptionsDecoder2 :: SetConfig()。

解决方法虽然令人不快,但却很简单,你必须展平界面,以便它包含继承的方法。在您的情况下将是:

[ComImport, Guid("EA5435EA-AA5C-455d-BF97-5F19DC9C29AD"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IClosedCaptionsDecoder2 
{
    // Methods inherited from IClosedCaptionsDecoder:
    [PreserveSig]
    int xxx(whatever...);
    // Methods specific to IClosedCaptionsDecoder2
    [PreserveSig]
    int SetConfig([In] ref ClosedCaptionsDecoderConfig config);
    [PreserveSig]
    int GetConfig([Out] out ClosedCaptionsDecoderConfig config);
}

这将于9月30日在美国成为法律,仅剩6周就能完成这项工作;)