这是从我的$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,IidParameterIndex = 1),输入,输出]参考对象实例);
我也试图UnmanagedType.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);
}
}
相关推荐
最新文章