从托管 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 代码中,以便我可以捕获用户交互并拥有它们由应用程序处理。
我看过一些文章,例如 这篇 MSDN 文章,但它在 VS/2003 中不起作用(编译器不喜欢委托语法)。
还有其他选择吗? 我认为我不能使用 DLLImport,因为我需要与特定的应用程序实例而不是平面 API 进行交互。
谢谢!
Bit of a history lesson here. I'm working on a legacy C++/MFC application and am trying to start a incremental modernization by pushing components written in C# (WinForms and later WPF).
I'm stucking using .Net/1.1 and VS/2003 for many reasons which are impossible to resolve in the near future.
Currently, as a proof of concept, something like this works:
#pragma push_macro("new")
#undef new
WinFormA::Form1* myform;
myform = __gc new WinFormA::Form1();
myform->ShowDialog();
#pragma pop_macro("new")
The problem I'm having is this - I need the unmanaged C++/MFC code to pass a callback pointer into the managed C# WinForm code so that I can capture user interactions and have them processed by the application.
I've looked at some articles such as this MSDN article but it doesn't work in VS/2003 (the compiler doesn't like the delegate syntax).
Are there any other options? I don't think I can use DLLImport since I need to interact with the specific application instance not a flat API.
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果其他答案不起作用,您始终可以编写一个 C 包装器来扁平化类。 例如,如果 C++ 类是:
我将编写一个包装器:
因为包装器是纯 C 语言,所以您可以随心所欲地在 C# 中 P/Invoke(void *This 应该变成 IntPtr以确保迁移到 64 位时的兼容性)。 有时,如果我真的雄心勃勃,我实际上会在 P/Invoke 周围编写一个 C# 包装器来“重新分类”事物。
If the other answers don't work out, you could always write a C wrapper to flatten the classes. For example, if the C++ class is:
I'll write a wrapper:
Because the wrapper is straight C, you can P/Invoke in C# to your heart's content (the void *This should become an IntPtr to ensure compatibility if you move to 64-bit). Sometimes, if I'm really ambitious, I'll actually write a C# wrapper around the P/Invokes to 're-classify' the thing.
我已经忘记了 .NET 1.*,但是:
定义必要的接口并将您的 .NET 组件注册为 COM 对象。 .NET 实用程序通常会提供相当好的封送代码。
如果可能,从 C++ 应用程序将它们作为 COM 对象访问,而无需任何托管 C++。 (使用接口指针而不是回调函数)。
如果 COM 不是一个选项,请使用 .NET Reflector 来查看自动生成的互操作程序集中发生了什么 - 这可能会让您了解如何手动执行相同的操作。
I already forgot .NET 1.*, but:
Define necessary interfaces and register your .NET components as COM objects. .NET utilities will usually provide reasonably good marshaling code.
If possible, access them as COM objects from C++ application without any Managed C++ at all. (Use interface pointers instead of functions for callbacks).
If COM is not an option, use .NET Reflector to see what's going on inside auto-generated interop assemblies - this might give an insight on how to do the same thing manually.
我从来没有亲自尝试过,但是你检查过.net1中肯定存在的RuntimeMethodHandle结构吗?
以及一些从 MSDN 的描述中复制粘贴的 .net2 Marshal::GetDelegateForFunctionPointer 方法:
I have never tried it by myself, but did you check RuntimeMethodHandle struct which is definitely exists in .net1?
And some copy-paste from MSDN's description .net2 Marshal::GetDelegateForFunctionPointer Method: