p/invoke 操作以执行另一个函数结束

Posted

技术标签:

【中文标题】p/invoke 操作以执行另一个函数结束【英文标题】:p/invoke operation ends up with executing another function 【发布时间】:2012-08-16 05:59:21 【问题描述】:

不知道为什么会这样,但是当我执行我的一个 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;
    ;

我被重定向到另一个由'prior'接口声明的函数。 例如,当我尝试执行以下命令时: 配置->设置配置(....)。重定向到的函数(或下一个要执行的命令),由 IClosedCaptionsDecoder2 的基类实现,称为 IClosedCaptionsDecoder

这个接口的c++声明是:

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 接口来解决这个问题。

【问题讨论】:

不应该像 C++ 接口那样从基础接口派生出 C# 接口吗? 设法通过在第二个界面中声明所有函数来解决这个问题 请不要更改问题的标题以将问题标记为已关闭。而是发布您的正确答案并通过单击答案旁边的空心复选标记将该答案标记为正确。 【参考方案1】:

这是在 CLR 中实现 COM 互操作的方式存在缺陷的副作用。当接口派生自 IUnknown 或 IDispatch 之外的另一个接口时,它不会正确地将接口的方法映射到 v-table 槽。它将第一个方法映射到第一个可用槽,即使它已经被具体 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 周的时间来实施;)

【讨论】:

以上是关于p/invoke 操作以执行另一个函数结束的主要内容,如果未能解决你的问题,请参考以下文章

qt的线程函数体结束意味着线程结束吗

局部变量 全局变量和存储属性

递归函数中的for循环在递归结束后继续

.Net调用非托管代码(P/Invoke与C++InterOP)

等到 for 循环内的所有函数调用结束其执行 - Javascript

jquery动画函数里面可以跟一个回调函数,表示动画结束后执行的代码