1

不知道为什么会这样,但是当我执行我的 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(),我猜是函数的offest有问题。

我什至尝试在 c# 端定义整个关系(继承等),但这也不起作用。

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

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

Edit2:我设法通过将所有功能添加到 IClosedCaptionsDecoder2 接口来解决这种情况。

4

1 回答 1

1

This is a side-effect of a flaw in the way COM interop is implemented in the CLR. It doesn't properly map methods of an interface to v-table slots when the interface derives from another interface other than IUnknown or IDispatch. It maps the first method to the first available slot even though it is already occupied by the methods of the inherited interface in the concrete coclass implementation. A side-effect of not supporting multiple inheritance. So what goes wrong is that when client code calls IClosedCaptionsDecoder::xxx(), it ends up calling IClosedCaptionsDecoder2::SetConfig() instead.

The workaround is straight-forward though unpleasant, you have to flatten the interface so it includes the inherited methods. In your case that will be:

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

This becomes law in the USA on September 30th, only 6 weeks left to get this working ;)

于 2012-08-16T10:28:16.837 回答