从C ++中的COM互操作的不叫回来管理对象的方法 [英] Returned managed object method not called from C++ in COM interop

查看:109
本文介绍了从C ++中的COM互操作的不叫回来管理对象的方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是从我的<一个跟进href="http://stackoverflow.com/questions/19465041/interop-com-isch-interface-marshaling-results-in-accessviotlationexception-on">$p$pvious帖子。阅读该职位的情况下。请注意,这是不严格COM互操作 - 但C ++接口是COM兼容

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

 类IPluginFactory:公共FUnknown
{
    虚拟tresult PLUGIN_API createInstance建立(FIDString CID,FIDString独立同分布的,无效** OBJ)= 0;
};
 

我的C#code是这样的:

  [ComImport]
[的Guid(Interfaces.IPluginFactory)
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)
公共接口IPluginFactory
{
    [preserveSig]
    [返回:的MarshalAs(UnmanagedType.Error)
    INT32的CreateInstance([IN] REF的Guid的classId,[在] REF的Guid interfaceId,[的MarshalAs(UnmanagedType.IUnknown),输入,输出]参考对象实例);
}
 

的实施分配一个新对象实例的实例参数和返回0(S_OK)。我甚至强制转换为预期的​​(管理)接口。

 实例=(IPluginBase)新PluginBase();
返回0;
 

返回的对象是由该C psented重新$ P $ ++接口:

 类IPluginBase:公共FUnknown
{
上市:
    虚拟tresult PLUGIN_API初始化(FUnknown *上下文)= 0;
    虚拟tresult PLUGIN_API终止()= 0;
};
 

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

  [ComImport]
[的Guid(Interfaces.IPluginBase)
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)
公共接口IPluginBase
{
    [preserveSig]
    [返回:的MarshalAs(UnmanagedType.Error)
    INT32初始化([的MarshalAs(UnmanagedType.IUnknown),在]对象上下文);

    [preserveSig]
    [返回:的MarshalAs(UnmanagedType.Error)
    INT32终止();
}
 

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

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

我的问题是:是的管理再$ P $的CreateInstance的psentation的声明是否正确? 我在想什么吗? (这应该是单纯功能的互操作,应该不是吗?)

其他建议的声明风格也受到欢迎。 感谢名单,马克。

编辑:这个问题似乎出在createInstance方法。我无法获取接口返回由独立同分布的参数要求。

  [preserveSig]
[返回:的MarshalAs(UnmanagedType.Error)
INT32的CreateInstance([IN] REF的Guid的classId,[在] REF的Guid interfaceId,[的MarshalAs(UnmanagedType.IUnknown,Iid​​ParameterIndex = 1),输入,输出]参考对象实例);
 

我也试图Unm​​anagedType.Interface结合的IidParameterIndex但都导致一个的IUnknown被封送回。如果我重新查询IPluginBase接口IPluginBase ::初始化方法的工作原理(断点管理code命中)。

解决方案
  

编辑:这个问题似乎出在createInstance方法。我是   无法获得接口返回的是受独立同分布问   参数。

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

 公众诠释createInstance建立(REF的Guid的classId,裁判的Guid RIID,楼盘的IntPtr实例)
{
    如果(比如!= IntPtr.Zero)
        返回E_POINTER;

    //代替实际的对象创建$ C $下的CreateObject
    obj对象=的CreateObject(的classId)

    //返回正确的接口
    IntPtr的UNK = Marshal.GetIUnknownForObject(OBJ);
    尝试
    {
        返回Marshal.QueryInterface(UNK,裁判RIID,出实例);
    }
    最后
    {
        Marshal.Release(UNK);
    }
}
 

This is a follow up from my previous post. Read that post for context. Note that it is not strict COM interop - but the C++ interfaces are COM compatible.

Im trying to implement this C++ interface in C#

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

My C# code looks like this:

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

The implementation assigns a new object instance to the 'instance' parameter and returns 0 (S_OK). I even cast to the expected (managed) interface.

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

The object returned is represented by this C++ interface:

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

Which looks like this in my C# implementation:

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

In the unmanaged C++ test application I wrote, I can successfully call createInstance and receive a non-null pointer the code uses as a IPluginBase*.

The problem comes when I try to call the 'initialize' method on this IPluginBase* pointer. It never reaches the managed code (no breakpoint is hit - other breakpoint work fine) and the return code is 0x80004003. It looks like the wrapper does some intercepting here...

My question is: is the declaration of the managed representation of CreateInstance correct? What am I missing here? (this should be plain vanilla interop, should it not?)

Other suggestions on declaration 'style' are also welcome. Thanx, Marc.

EDIT: The problem seems to lie with the createInstance method. I am unable to get the interface returned that is asked for by the iid parameter.

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

I have also tried UnmanagedType.Interface in combination with the IidParameterIndex but both result in a IUnknown being marshaled back. If I re-query the IPluginBase interface the IPluginBase::initialize method works (breakpoint in managed code hits).

解决方案

EDIT: The problem seems to lie with the createInstance method. I am unable to get the interface returned that is asked for by the iid parameter.

Specifying IidParameterIndex doesn't help here. Your implementation of createInstance should look like this:

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

这篇关于从C ++中的COM互操作的不叫回来管理对象的方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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