从托管C#回调非托管代码

时间:2009-06-26 10:02:46

标签: c# c++ interop callback managed-c++

这里有一段历史课。我正在研究遗留的C ++ / MFC应用程序,并试图通过推送用C#(WinForms和更高版本的WPF)编写的组件来开始增量现代化。

我坚持使用.Net / 1.1和VS / 2003有很多原因,这些原因在不久的将来是无法解决的。

目前,作为一个概念证明,这样的工作:

#pragma push_macro("new")
#undef new

WinFormA::Form1* myform;
myform = __gc new WinFormA::Form1();
myform->ShowDialog();

#pragma pop_macro("new")

我遇到的问题是 - 我需要非托管C ++ / MFC代码将回调指针传递给托管C#WinForm代码,以便我可以捕获用户交互并让应用程序处理它们。

我查看了一些文章,例如this MSDN article,但它在VS / 2003中不起作用(编译器不喜欢委托语法)。

还有其他选择吗?我不认为我可以使用DLLImport,因为我需要与特定的应用程序实例进行交互而不是平面API。

谢谢!

3 个答案:

答案 0 :(得分:1)

如果其他答案无法解决,您可以随时编写C包装器来展平类。例如,如果C ++类是:

class TheClass {
  public:
    TheClass(int Param);
    ~TheClass();

    bool SomeFunction(int Param1,int Param2);
};

我会写一个包装器:

extern "C" void *TheClass_Create(int Param) {
  return (void*) new TheClass(Param);
}

extern "C" void TheClass_Destroy(void *This) {
  delete (TheClass*) This;
}

extern "C" bool TheClass_SomeFunction(void *This,int Param1,int Param2) {
  return ((TheClass*) This)->SomeFunction(Param1,Param2);
}

因为包装器是直的C,你可以在C#中调用你的心脏内容( void *这个应该成为一个IntPtr,以确保你移动到64位时的兼容性)。有时,如果我真的雄心勃勃,我实际上会在P / Invokes周围编写一个C#包装器来“重新分类”这个东西。

答案 1 :(得分:0)

我已经忘记了.NET 1. *,但是:

定义必要的接口并将.NET组件注册为COM对象。 .NET实用程序通常会提供相当好的编组代码。

如果可能,从C ++应用程序访问它们作为COM对象,根本不需要任何托管C ++。 (使用接口指针而不是回调函数)。

如果COM不是一个选项,请使用.NET Reflector查看自动生成的互操作程序集内部发生了什么 - 这可能会让您深入了解如何手动执行相同操作。

答案 2 :(得分:0)

我自己从未尝试过,但你检查过.net1中肯定存在的RuntimeMethodHandle结构吗?

SomeDelegate Handler = new SomeDelegate(SomeMethod);
IntPtr HandlerPtr = Handler.Method.MethodHandle.GetFunctionPointer();

来自MSDN描述的一些复制粘贴.net2 Marshal :: GetDelegateForFunctionPointer 方法:

  

在.NET Framework的1.0和1.1版中,可以将表示托管方法的委托作为函数指针传递给非托管代码,允许非托管代码通过函数指针调用托管方法。非托管代码也可以将该函数指针传递回托管代码,并且指针已正确解析为基础托管方法。