【從業余項目中學習2】C# 實現調用Matlab函數(Visual Studio:2008, Matlab:R2009a)


  最近正在給客戶做的個人項目,要求實現C#與Matlab之間的調用,即C# winform界面收集用戶輸入的參數,將參數傳遞給Matlab的算法計算,Matlab函數返回的結果顯示在winform界面上。

  網上此類的文章較多,但自己在實現過程中還是有些差別,所以在項目進行之前,自己寫了一個測試的例子來實現C#對Matlab函數的調用

一.  測試用例簡介

  功能:Matlab函數計算兩個數值a與b的和,a與b的值由C#提供,和值c經Matlab計算得出后,返回給C#

  環境:Microsoft Visual Studio 2008

     Matlab R2009a(Version 7.8.0.347)

  備注:由官網可知,Matlab對類似其他程序調用都提供了很好的支持,這里沒有選擇VS版本大於Matlab版本,是因為擔心Matlab版本只支持自己之前的VS版本。

 

二.  實現步驟

  1. 實現Matlab函數

    A. 打開Matlab R2009a,新建testAdd.m文件

    B. testAdd.m中實現加法函數

1 function y = testAdd(a, b)
2 y = a + b;

 

  2. 編譯testAdd.m,得到DLL文件,以便由C#引用

    A. 在Matlab命令行中輸入"deploytool",即可彈出"Deployment Tool"工具窗口

      在網上看很多資料,執行"deploytool"命令之前都需要安裝Matlab編譯器(命令:"mbuild -setup"),但我不這樣做,也可編譯。懷疑是否與我將VS,Matlab都裝在一台機器有關。另外即便我執行這安裝命令,也找不到正確的編譯器。總之,我並沒有按照網上教程,直接"deploytool"即可。這也提醒自己:實踐過后,才知是否正確,不要盲目聽從別人方法。

    B. 編譯DLL,需要在"Deployment Tool"工具窗口中新建Deployment project

      這里我建了名為"test"的工程,選擇project類型時,應選擇.NET Component,因為這里我需要其作為C#的引用。同時注意這里的工程名,即是你編譯出DLL的名稱,同時C#程序調用時,"Test"即為封裝Matlab函數的類名。他將你的工程名,首字母大寫用為高級語言中的類名。

    C. 配置"test" project

      首先將testAdd.m添加到test工程下Test文件夾中(右擊Test,選擇Add File)(注意:這里不要使用中文路徑,詳見下方六.測試過程中Bug記錄)。

      其次選擇Setting,在設置中,配置.NET Microsoft Framework,由"Default"改為"2.0",不能用默認。網上說法是否則編譯出的DLL會有問題。

      注意:這里網上許多資料講,要將Assembly Type設置為Shared,但我發現如果這樣,必須要提供Encryption Key的文件路徑,這個就沒法提供了。所以我並沒有這樣做,事實上沒有影響。疑惑的地方。

    D. 點擊"Build"編譯文件(如下圖所示)

      

     即可在test\src路徑下得到編譯后的DLL文件

     

  3. 實現C#程序,調用Matlab編譯出的DLL

    A. C#項目中,導入Matlab DLL引用

      導入的文件:test.dll, testNative.dll, MWArray.dll(%matlabpath%\toolbox\dotnetbuilder\bin\win32\v2.0,MWArray是用於C#與Matlab之間的數據交換類,傳值,取結果都用到它)

    B. 實現C#調用代碼

 1 using System.Data;
 2 using System.Drawing;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Windows.Forms;
 6 using MathWorks.MATLAB.NET.Utility;
 7 using MathWorks.MATLAB.NET.Arrays;
 8 using test;
 9 
10 namespace testMatlab
11 {
12     public partial class Form1 : Form
13     {
14         public Form1()
15         {
16             InitializeComponent();
17 
18             label6.Text = "";
19         }
20         
21         private void button1_Click(object sender, EventArgs e)
22         {
23             //Get input number from UI
24             int iTextBox1 = int.Parse(textBox1.Text.ToString());
25             int iTextBox2 = int.Parse(textBox2.Text.ToString());
26                         
27             MWArray result = null;
28             MWNumericArray a = new MWNumericArray(iTextBox1);
29             MWNumericArray b = new MWNumericArray(iTextBox2);
30 
31             
32             //call function testAdd, provided by Matlab
33             Test t = new Test();
34             result = t.testAdd((MWArray)a, (MWArray)b);
35 
36 
37             int y = ((MWNumericArray)result).ToScalarInteger();
38             
39             //show result in UI
40 
41             textBox3.Text = y + "";
42             label6.Text = "Get the result by Matlab DLL, Answer: " + y;
43         }
44     }
45 }

 

三.  執行C# winform程序,驗證計算結果,確定是否執行了Matlab函數調用

    1. 輸入初值

   

    2. 得到結果

   

    

四.  小結

  由此,可實現C#對Matlab算法的調用。當然這里只是自己開發需要時,設計的一個小例子。由於Matlab計算,輸入與結果需要大量的矩陣,那C#與其之間的數據交換也是通過MWArray進行,只要遵循接口規范,都可以實現。這里不再研究,網上資料也很多。

  

五.  完整的測試例子附件

  Matlab函數:http://files.cnblogs.com/KevinSong/testMatlab.zip

  C#程序:http://files.cnblogs.com/KevinSong/Test.zip

 

.  測試過程中Bug記錄

  1. 調用DLL時,程序報錯"MathWorks.MATLAB.NET.Utility.MWMCR.mclCreateComponentData,錯誤描述是:傳遞給系統調用的數據區域太小"

    解決方法:不能使用中文路徑的.m文件,可能會有詭異的問題產生

    參考鏈接:http://hi.baidu.com/ssemo/item/4caab7f3a0765ec20dd1c888

 

雖然網上參考資料很多,但經過自己實踐,還是發現一些不同的小地方。項目進行前,通過一個小的測試例子來證明技術路線可行。希望對需要的同學有幫助。拋磚引玉:-)

 

Best Regards

Kevin Song

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM