不从C ++中COM互操作称为返回管理对象方法(Returned managed object me

2019-10-18 19:31发布

这是从我的后续以前的文章 。 阅读该职位背景。 请注意,它不是严格的COM互操作 - 但C ++接口是COM兼容。

我试着去C#实现这个C ++接口

class IPluginFactory : public FUnknown
{
    virtual tresult PLUGIN_API createInstance (FIDString cid, FIDString iid, void** obj) = 0;
};

我的C#代码如下所示:

[ComImport]
[Guid(Interfaces.IPluginFactory)]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IPluginFactory
{
    [PreserveSig]
    [return: MarshalAs(UnmanagedType.Error)]
    Int32 CreateInstance([In] ref Guid classId, [In] ref Guid interfaceId, [MarshalAs(UnmanagedType.IUnknown), In, Out] ref object instance);
}

执行情况的新的对象实例分配给“实例”参数,并返回0(S_OK)。 我甚至强制转换为预期的(管理)界面。

instance = (IPluginBase)new PluginBase();
return 0;

返回的对象通过该C ++接口表示:

class IPluginBase: public FUnknown
{
public:
    virtual tresult PLUGIN_API initialize (FUnknown* context) = 0;
    virtual tresult PLUGIN_API terminate () = 0;
};

它看起来像这样在我的C#实现:

[ComImport]
[Guid(Interfaces.IPluginBase)]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IPluginBase
{
    [PreserveSig]
    [return: MarshalAs(UnmanagedType.Error)]
    Int32 Initialize([MarshalAs(UnmanagedType.IUnknown), In] object context);

    [PreserveSig]
    [return: MarshalAs(UnmanagedType.Error)]
    Int32 Terminate();
}

在非托管C ++测试应用程序我写的,我可以成功调用createInstance建立和接收代码使用一个非空指针作为IPluginBase *。

问题是当我尝试调用这个IPluginBase *指针“初始化”的方法。 它永远不会到达托管代码(无断点命中 - 其他断点做工精细)和返回代码0x80004003。 它看起来像包装在这里做了一些拦截...

我的问题是:是的CreateInstance的管理表示的声明是否正确? 我缺少的是在这里吗? (这应该是普通的香草互操作,应该不是吗?)

关于申报“风格”的其他建议也欢迎。 感谢名单,马克。

编辑:这个问题似乎在于与createInstance方法。 我无法获取接口返回由IID参数要求。

[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
Int32 CreateInstance([In] ref Guid classId, [In] ref Guid interfaceId, [MarshalAs(UnmanagedType.IUnknown, IidParameterIndex = 1), In, Out] ref object instance);

我也曾尝试UnmanagedType.Interface结合的IidParameterIndex但两者导致的IUnknown被编回来。 如果我重新查询IPluginBase接口IPluginBase ::初始化方法作品(断点在托管代码中命中)。

Answer 1:

编辑:这个问题似乎在于与createInstance方法。 我无法获取接口返回由IID参数要求。

指定IidParameterIndex没有帮助在这里。 您执行createInstance应该是这样的:

public int createInstance(ref Guid classId, ref Guid riid, ref IntPtr instance)
{
    if (instance != IntPtr.Zero)
        return E_POINTER;

    // substitute your actual object creation code for CreateObject
    object obj = CreateObject(classId) 

    // return the correct interface
    IntPtr unk = Marshal.GetIUnknownForObject(obj);
    try
    {
        return Marshal.QueryInterface(unk, ref riid, out instance);
    }
    finally
    {
        Marshal.Release(unk);
    }
}


文章来源: Returned managed object method not called from C++ in COM interop