[C++/C#]用C#去調用C++寫的DLL,並透過CallBack傳遞

這三天開始學C#視窗語言,寫C++久了,自然對很多地方的覺得很困惑,花很多時間在探索class結構,Form元件控制,message傳遞這些的。其實最主要的是自己寫的C++ DLL,有客戶拿去用C#來開發,遇到一些問題問我,我完全沒辦法解,只好自己跳下來瞭解。

會用到以下的元件與方法:
- DLL匯出(C++)
- CallBack函式(C++)
- DLL匯入(C#)
- Delegate with CallBack(C#)

所以,這整個架構是這樣的:
  1. 在C++端,定義好供給外部呼叫的函式,CallBack函式。為了清楚,用Dialog的方式呈現。
  2. 在C#端,定義使用的的函式,再加上處理C++端透過CallBack丟回來的值。
為何要用CallBack,因為C#端不知道何時C++要丟個值過來,是一個被動角色,所以利用C++透過CallBack是最好方式。說得很簡單,其實也真的不難,只要遵循C++和C#規定的架構,訂好規則就可以通了。
流程如下:
  • 首先需要以VC++建立一個DLL,而為了讓彼此溝通更容易瞭解,用Dialog來呈現,因此首先需要新增一個「MFC DLL」專案。

  • 這時後會只有一個可以使用MFC元件的單純框架,再來我們去資源檢視分頁,加入「Dialog」資源。在dialog上拉元件過來,一個Editor,一個Button,分別命名,並定義按下Button的事件處理。放著。
  • 定義C++要被呼叫的函式,CallBack函式等的,利用「extern "C" __declspec (dllexport)」,並寫名這些函式要幹麼。比方說我有這些函式:
    • ProgressCallback - CallBack函式,定義參數為一個int,C++裡頭呼叫這個函式就可以讓所有宣告這個CallBack的人都收到。
    • CreateRandomDialog - 叫出上述的視窗出來
    • SetCallBack - 讓外部程式設定CallBack。
  • C++ 寫完Compile好後就可以得到DLL
  • 再來去C#端,這就可以開一個「Windows Forms Application」
  • 開完後去Form1.cs,拉拉元件,一個Button,兩個Label。Button用來開啟C++ Dialog,Label用來呈現CallBack丟回來的值。定義好後就點兩下Button進去準備開始了。
  • 宣告CallBack需要的關鍵字是「delegate」,引用DLL用的關鍵字是「DllImport」,呼叫DLL的函式來用的關鍵字是「extern」。code如下:
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate void ProgressCallback(int value);//CallBack
[DllImport("testMFCDLL.dll")]
public static extern void CreateRandomDialog();
[DllImport("testMFCDLL.dll")] // 每一個function都要加引用
public static extern void SetCallBack([MarshalAs(UnmanagedType.FunctionPtr)]  ProgressCallback CallBackFun);
public Form1()
{
    InitializeComponent();
    //ProgressCallbackCSharp//是C#端處理的函式
    ProgressCallback CallBackFun = new ProgressCallback(ProgressCallbackCSharp);
    SetCallBack(CallBackFun);
}

private void buttonAbout_Click(object sender, EventArgs e)
{
    CreateRandomDialog();//透過dll去叫出C++的Dialog
    buttonAbout.Enabled = false;//呼叫C++ Dialog後把Button給Disable,避免重複按
}

public void ProgressCallbackCSharp(int value)
{
    if (value == -1)//等於-1的話表示關閉,在C++那邊關閉後會丟出"-1"的值
        buttonAbout.Enabled = true;//Button重新可以點選
    else
        TextLabel.Text = value.ToString();//在label上show出值
    //MessageBox.Show(value.ToString());
}

--程式執行圖--
--完整Source Code(VC++ 2008 vaildated + VC# 2010 vaildated)
Download C++ Code
Download C# Code



2 意見:

學習筆記 提到...

It helps me a lot, thank you very much

Jason Yi 提到...

受益良多,感謝!

搜尋此網誌

總網頁瀏覽量

TK呱呱

Made with by TK