c# - 在 C# 中实现 DISPID_VALUE 并从 C++ 中调用它

标签 c# c++ com

我有一个接受 IDispatch 接口(interface)并在特定条件下使用 DISPID_VALUE 调用它们的 C++ COM 模块。这种方法在 C++ 中工作得很好。现在我在 C# 中有一个客户端,我想实现一个对象,该对象实现了 IDispatch 并具有 DISPID = 0(DISPID_VALUE) 的方法。我已经试过了:

// This will generate invalid cast
[ComVisible(true)]
class Callback1
{
    [DispId(0)]
    void Execute(object arg) {...}
}

// This also generate invalid cast
[ComVisible(true)]
[Guid("163AC24E-90DB-47D4-8580-EBB21E981FBF"),
    InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
interface ICallback2
{
    [DispId(0)]
    void Execute(object arg) ;
}
[Guid("842A7754-7CE6-4991-9E12-3FAB2367591A"),
    ClassInterface(ClassInterfaceType.None),
    ComSourceInterfaces(typeof(ICallback2))]
class Callback2 : ICallback2
{
    public void Execute(object arg) {}
}

另外,我不记得是如何实现的,但我也编写了一个成功转换但根本不调用任何内容的代码。现在我想知道我应该如何编写一个实现 IDispatch 的类,并在 DISPID = 0 时调用特定方法。

转换异常是:

System.InvalidCastException was unhandled
  Message=Specified cast is not valid.
  Source=mscorlib
  StackTrace:
   at System.StubHelpers.InterfaceMarshaler.ConvertToNative(Object objSrc, IntPtr itfMT, IntPtr classMT, Int32 flags)
   at nmclientLib.INMAsyncOperation.AddCallback(Object pCallback)
   at NMTools.RecorderRegistration.BeginConnection(OperationDoneHandler h) in D:\Programming\Version 0.9\A_Project\NMTools\RecorderRegistration.cs:line 166
   at NMTools.ConnectionManager.NoRequestRegisterConnection(RecorderRegistration r, Boolean bConnect) in D:\Programming\Version 0.9\A_Project\NMTools\ConnectionManager.cs:line 396
   at NMTools.ConnectionManager.<InitializeFromDatabase>b__0(Object s, EventArgs e) in D:\Programming\Version 0.9\A_Project\NMTools\ConnectionManager.cs:line 339
   at System.Windows.Forms.Timer.OnTick(EventArgs e)
   at System.Windows.Forms.Timer.TimerNativeWindow.WndProc(Message& m)
   at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
   at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
   at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
   at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
   at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
   at System.Windows.Forms.Application.Run(Form mainForm)
   at TestApp1.Program.Main() in D:\Programming\Version 0.9\A_Project\TestApp1\Program.cs:line 18

内部异常:

最佳答案

好的,从评论中可以看出是什么问题。您必须声明 [ComVisible] 接口(interface)和类 public。 CLR 尊重可访问性,当 .NET 程序也不能使用内部类型时,COM 客户端不能使用内部类型。

更好的异常消息会更好,但这对于 COM 错误处理类(class)来说是同等的。它没有任何类似于可访问性约束的内容,因此没有比 E_NOINTERFACE 更具体的错误代码。它被翻译成 InvalidCastException。

值得注意的是,这种情况非常罕见,在 .NET 应用程序中使用 [ComVisible] .NET 类没有多大意义。只需通过添加对程序集的引用来直接使用该类。您将摆脱注册要求、错误消息和方法调用中的大量开销。取模某种您无法摆脱的 COM 层,这种情况会发生。

关于c# - 在 C# 中实现 DISPID_VALUE 并从 C++ 中调用它,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13893717/

相关文章:

c# - Xamarin Android App 导致设备重启

c# - 术语 "true"面向对象是什么意思

c++ - 使用shrink_to_fit()释放 vector vector 中的内存

java - 使用图表 X 的 VC++ 图表

c# - JQuery AJAX,错误状态代码 : 200, 状态文本:parserorro |好的

c# - 使 Windows 窗体应用程序可移植

c++ - 如何在 VBScript 中使用 BSTR 参数调用 C++ COM 函数

c++ - C++ COM(ATL)中添加新接口(interface)需要注意什么

c++ - 初始化堆分配对象时出错

c++ - glColor3f 仅颜色为红色