在我的下一个项目中我想为C++中已有的代码实现GUI。 我的计划是将C++部分封装在一个DLL中,并在C#中实现GUI。我的问题是,我不知道如何实现从非托管DLL到管理C#代码的回调。我已经在C#中进行了一些开发,但托管代码和非托管代码之间的接口对我来说是新的。任何人都可以给我一些提示或阅读提示或从一个简单的例子开始?不幸的是我找不到任何有用的东西。Howto实现回调接口从非托管DLL到.net应用程序?
回答
您不需要使用Marshal.GetFunctionPointerForDelegate(),P/Invoke编组会自动执行。您需要在C#端声明一个委托,该委托的签名与C++端的函数指针声明兼容。例如:
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
class UnManagedInterop {
private delegate int Callback(string text);
private Callback mInstance; // Ensure it doesn't get garbage collected
public UnManagedInterop() {
mInstance = new Callback(Handler);
SetCallback(mInstance);
}
public void Test() {
TestCallback();
}
private int Handler(string text) {
// Do something...
Console.WriteLine(text);
return 42;
}
[DllImport("cpptemp1.dll")]
private static extern void SetCallback(Callback fn);
[DllImport("cpptemp1.dll")]
private static extern void TestCallback();
}
,并用于创建非托管的DLL对应的C++代码:
#include "stdafx.h"
typedef int (__stdcall * Callback)(const char* text);
Callback Handler = 0;
extern "C" __declspec(dllexport)
void __stdcall SetCallback(Callback handler) {
Handler = handler;
}
extern "C" __declspec(dllexport)
void __stdcall TestCallback() {
int retval = Handler("hello world");
}
这足以让你开始用它。有一百万个细节可以让你陷入困境,你一定会遇到其中的一些问题。获得这种代码的更有效的方法是用C++/CLI语言编写一个包装器。这也可以让你包装一个C++类,这是P/Invoke无法做到的。一个体面的教程是available here.
请参阅Marshal.GetFunctionPointerForDelegate,它将为您提供一个函数指针,用于从非托管代码调用托管(即C#代码)。
P/Invoke可以处理将托管委托编组到一个函数指针。因此,如果您公开从DLL注册回调函数的API,并在C#中将代理传递给该函数。
在MSDN上有一个关于EnumWindows函数的例子。在这篇文章中要小心,要注意第4点,指出行:
然而,如果回调函数可以 可以在调用返回后调用时, 托管调用方必须采取措施,以 保证该代表仍保持 未收集,直到回调函数 完成。有关详细信息 有关防止垃圾收集的信息,请参阅Interop Marshaling 及平台调用。
那是什么要说的是,你需要确保你的委托是没有收集到后,托管代码由要么保持在你的代码对它的引用,或牵制它做叫它垃圾。
+1对于批判 - 单独使用P/Invoke只能保证指针在调用期间的有效性 - 如果你正在缓存它,你需要钉住它(不能说存储引用,可疑,但这并不意味着:-) – 2013-01-08 21:28:11
- 1. 从非托管dll中的QThread回调到托管C++主线程
- 2. 非托管dll调用崩溃一个dotnet应用程序?
- 3. 几个应用程序域调用相同的非托管dll
- 4. C#托管的dll调用或非托管的dll调用?
- 5. 从C#调用非托管C++类DLL#
- 6. 从VB调用非托管的DLL
- 7. 从C调用非托管dll困难#
- 8. 非托管dll的LoadLibrary返回ASP.NET应用程序中的IntPtr.Zero
- 9. 使用.NET应用程序未知/非托管的DLL的 - 获取未知DLL
- 10. 中止调用到非托管DLL
- 11. 如何从非托管应用程序中延迟加载托管的DLL?
- 12. 从C#应用程序中的非托管DLL导入函数
- 13. 在混合C++ .NET应用程序中强调托管还是非托管?
- 14. 调试托管的.NET代码从非托管C++调用
- 15. 在VB .NET中的非托管DLL的回调函数
- 16. 从托管代码调用非托管DLL函数时出错
- 17. 如何从托管C++调用非托管DLL
- 18. 从C#WPF应用程序调用非托管Windows DLL时出错
- 19. 从没有COM的非托管C++应用程序调用C#dll
- 20. 如何从非托管应用程序
- 21. 我如何从托管代码调用外部非托管应用程序?
- 22. 接口实现回调 - 管理
- 23. 问题只在Vista(.net):调用非托管dll(Shell32.dll,函数:SHEmptyRecycleBin)线程
- 24. 从.NET实例化非托管类
- 25. 如何将数据从非托管应用程序传递到C#COM DLL
- 26. 链接错误 - >托管DLL到非托管库
- 27. .NET Web服务 - 如何调用非托管C DLL
- 28. 如何在混合应用程序中执行异常处理? (托管应用程序使用非托管DLL)
- 29. 在WPF应用程序中加载非托管DLL
- 30. 非托管的DLL
谢谢nobugz,我会尽快尝试。我希望我不会陷入太多麻烦;-) – chrmue 2010-01-30 18:04:51
完美地为我工作,再次感谢! – chrmue 2010-02-15 13:39:01