在我的下一個項目中我想爲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. 從C#.NET調用非託管DLL所需的教程
- 2. 在非託管cpp中實現C#接口dll
- 3. 從非託管dll中的QThread回調到託管C++主線程
- 4. 非託管dll調用崩潰一個dotnet應用程序?
- 5. 幾個應用程序域調用相同的非託管dll
- 6. C#託管的dll調用或非託管的dll調用?
- 7. 使用.NET應用程序未知/非託管的DLL的 - 獲取未知DLL
- 8. 非託管dll的LoadLibrary返回ASP.NET應用程序中的IntPtr.Zero
- 9. 從C#調用非託管C++類DLL#
- 10. 從非託管的DLL調用函數
- 11. 從VB調用非託管的DLL
- 12. 從C調用非託管dll困難#
- 13. 中止調用到非託管DLL
- 14. 從非託管win32程序集DLL調用託管代碼 - 崩潰
- 15. 實現一個C#DLL COM文件在非託管C++程序
- 16. 如何從非託管應用程序中延遲加載託管的DLL?
- 17. 從C#應用程序中的非託管DLL導入函數
- 18. 在混合C++ .NET應用程序中強調託管還是非託管?
- 19. 調試託管的.NET代碼從非託管C++調用
- 20. 在VB .NET中的非託管DLL的回調函數
- 21. 調試非託管的dll
- 22. 從託管代碼調用非託管DLL函數時出錯
- 23. 如何從託管C++調用非託管DLL
- 24. 從沒有COM的非託管C++應用程序調用C#dll
- 25. 從C#WPF應用程序調用非託管Windows DLL時出錯
- 26. 如何從非託管應用程序
- 27. 問題創建一個非託管常規MFC DLL和從託管C++ .NET應用程序
- 28. 非託管C++代碼導致崩潰到.Net應用程序
- 29. 問題只在Vista(.net):調用非託管dll(Shell32.dll,函數:SHEmptyRecycleBin)線程
- 30. 我如何從託管代碼調用外部非託管應用程序?
謝謝nobugz,我會盡快嘗試。我希望我不會陷入太多麻煩;-) – chrmue 2010-01-30 18:04:51
完美地爲我工作,再次感謝! – chrmue 2010-02-15 13:39:01