C#和MatLab的混合編程,充分利用了winform的直觀顯示和matlab的強大計算能力。在此以一個小例子的形式給大家講述一下二者混合編程的實現。
一、軟件的配置說明
C#版本:VS2010;MatLab版本:MatLab2011a
二、制作matLab的C# dll文件
2.1首先寫一個M文件(實現你想要的函數執行形式)
以網上down了一個M文件(實現基本的繪圖功能),內容見下表,
function test(h,D) for x=-10:0.1:10, if x>D y=h; hold on; plot(x,y) elseif x<-D y=-h; hold on; plot(x,y) else y=h/(D*x); hold on; plot(x,y) end end
2.2 創建制作的dll文件的工程
在MatLab的命令窗口中,輸入deploytool,或者利用菜單選項,file-new-deployment project打開創建dll文件的工程創建窗口,如下圖所示。
在圖中,主要分為以下三部分,Name:你想要命名的名字,prj是工程的后綴(一般不忽略);location:創建工程的儲存位置;type:針對c#而言,我們需要選擇.net assembly這一項;點擊Ok選項,工程已經創建完畢。下一步就是向工程中加入你想要的方法等元素。
2.3 向所建工程中添加對應的元素
上述過程中,就相當於在C#中創建了Untitled2的命名空間,需要在此添加對應的類和方法。基於上述的例子,下一步,我們在窗體菜單中 destop-.netAssembly-點擊選擇,見下圖所示。
在上面Classes是你自己對應編寫了一個類,然后向里面添加Add files,也就是你之前編寫的M文件,經過編譯之后,就在對應的工程文件中,形成你所需要的dll文件。下一步我們如何在C#中利用對應的dll文件。
三、如何在C#中利用Matlab制作的dll文件
3.1首先,將matlab中對應的剛編寫好的untitled的dll文件,同時從C:\Programs\Files\MatLab\R2011a\toolbox\dotnetbuilder\bin\win64\v2.0中拷貝出MWArrary.dll和ManagedCPPAPI.netModule三個文件拷貝到C#編寫的工程文件中去,C#編程文件的debug文件中。在這里特別說明的一點是:最后一個文件在matlab2011a中沒有找到對應的文件,發現並不影響程序的執行。
3.2在C#的工程中,我們在引用中----添加對彼此dll文件的引用。見下圖
3.3命名空間的引用 using.....的書寫
using MathWorks.MATLAB.NET.Arrays;
using MathWorks.MATLAB.NET.Utility;
using Untitled1;
四、最后,在C#中如何引用這些matlab提供的計算模塊的功能實現
4.1 在C#中調用MatLab的函數是最重要的是函數變量之間的傳遞是如何實現的?
包括以下幾個問題:a、將C#的參數帶入到matLab的函數的參數中,將C#的參數轉化成對應的MWArray類型。
b、如何將Matlab函數返回的類型,轉化成C#對應的函數類型。
4.2 MWNumericArray是MWArray和c#中數據的中間類,實現C#與matlab間傳遞參數的功能
a.double型、int型等數值類型的變量傳遞
MWNumericArray i = null, result = mydouble;
i=4;
myClass myclass = new myClass(); //實例化
result = (MWNumericArray)myclass.myfunc(i);
b.字符串(需要用到MWCharArray和MWArray轉換)
MWCharArray FileName = myString;
MWNumericArray sensitivity;
sensitivity = (MWNumericArray)myClass.myAlgorithm((MWArray)FileName);
c.多個輸出參數組成的數組
MWNumericArray out_Arr = (MWNumericArray)out_Args[1]; //取出第一個參數返回的數組(matlab返回的數組下界是從1開始的)
取出數組中的一個元素值
mydouble=out_Arr[i].ToScalarDouble();
如上面例子ToScalarDouble一類的toXXXX等方法還有許多。
d.result.toArray可以把matlab返回的矩陣變成C#的n x m數組,eg:
double[,] csArray= (double[,])result.ToArray(MWArrayComponent.Real);
e.將數組傳入Matlab(和傳遞單個數值的方法一樣)
double[,] dbx = new double[2, 2] { { 1, 2 }, { 3, 4 } };
MWNumericArray x=dbx;
myclass.picture(x);
testz.testzclass st = new testz.testzclass(); MWArray[] max = st.testz(2); MWNumericArray x1 = (MWNumericArray)max[0]; MWNumericArray x2 = (MWNumericArray)max[1]; double[,] location1 = (double[,])x1.ToArray(MWArrayComponent.Real); double[,] location2 = (double[,])x2.ToArray(MWArrayComponent.Real); label1.Text = location1[1,2].ToString(); 其中的M文件: Code function [x1,x2]=testz() x1=[1 2 3; 4 5 6; 7 8 9;]; x2=[9 8 7; 6 5 4; 3 2 1;]
常用的轉換函數:
① public Array ToArray(MWArrayComponent component);
將M類型轉換成C#的Array類型,然后可以直接轉換成其它類型的數組。
② public byte ToScalarByte();
將M類型轉換成C#的字節類型;
③ public double ToScalarDouble();
將M類型轉換成C#的雙精度類型;
double temp = ((MWNumericArray)(mwArgout[0])).ToScalarDouble();
④ public float ToScalarFloat();
將M類型轉換成C#的單精度類型;
⑤ public int ToScalarInteger();
將M類型轉換成C#的整型類型;
⑥ public long ToScalarLong();
將M類型轉換成C#的長整C/C++/C#數據型類型;
⑦ public short ToScalarShort();
將M類型轉換成C#的短整型類型;
⑧ public override string ToString();
將M類型轉換成C#的字符串類型;string arror = mwArgout[2].ToString();
⑨ public Array ToVector(MWArrayComponent component);
將M類型轉換成C#的Array類型,然后可以直接轉換成其它類型的數組。
下面使用調試過的代碼示例表述①⑨兩個函數的區別:
①
double[,] Temp1 = new double[1,3];
Temp1= (double[,])((MWNumericArray)mwArgout[1]).ToArray(MWArrayComponent.Real);
⑨
double[] s1 = new double[2];
s1 = (double[])((MWNumericArray)mwArgout[1]).ToVector(MWArrayComponent.Real);
從以上代碼可以看出:函數①得到了二維數組,而⑨則是得到了一維數組。轉換成C++/C#數據類型后,它們的維數均為從0開始。
最后總結:
C++/C#數據類型到M類型
此方向轉換十分簡單。
如果C++/C#數據不是數組,
直接將值傳遞給已經初始化的MWArray數組中的成員
直接將數據類型賦值給已經初始化的MWNumericArray變量。
直接將字符串類賦值給已經初始化的MWCharArray變量。
如果是數組類型:
直接賦值給MWNumericArray變量;
賦值給MWArray變量,則在前面加上類型轉換如:(MWNumericArray)進行強制轉換。
總之,MWArray是總類型,其它的以MW開頭,以Array結尾的變量類型都可以直接對它進行賦值或取值。
M類型到C++/C#數據類型
MWArray
M類型,它是M文件的編譯后內部的標准類型,一切C++/C#類型都要最終轉換成此類型,方可作為參數調用M語言函數。
MWCharArray
M的字符串類型,使用它可以將M中的字符類型轉換成C++/C#的字符串類型。
MWNumericArray
MWNumericArray是MWArray與C#等語言的轉換中間類型。
上述整理參考了文獻出自http://zxfcool2000.blog.163.com/blog/static/31852320101117111555598/
在實現過程中遇到的問題:
錯誤信息:“未能加載文件或程序集“MWArray, Version=2.11.1.0, Culture=neutral, PublicKeyToken=e1d84a0da19db86f”或它的某一個依賴項。試圖加載格式不正確的程序。”
解決方案:將C#項目屬性從x86->x64就行了
補充一個例子的應用:
M文件:
function [x1,x2]=test(x3) x1=[1 x3*x3 x3; 1-x3 5 6; 7 8 9;]; x2=[9 8 7; 6 5 4; 3 2 1;];
在C#中形成的幾種函數形式如下:
public MWArray test();
public MWArray[] test(int numArgsOut);
public MWArray test(MWArray x3);
public MWArray[] test(int numArgsOut, MWArray x3);
public void test(int numArgsOut, ref MWArray[] argsOut, MWArray[] argsIn);
所以在C#中可以選擇不同的形式調用,其中numArgsOut指的是輸出參數的個數 argsOut:輸出參數,當然盡管C#中泛泛提出了幾種函數形式,確只有第3,4,5是可以使用的(結合自己寫的M文件內容)
脫離matlab安裝的環境下,如何實現程序的運行自如:
通過com組建的形式進行混合編程,如果機器上沒有安裝MATLAB,編譯生成的軟件照樣可以使用,但是需要安裝MATLAB提供的MATLAB Compiler Runtime,這個軟件在MATLAB的安裝目錄下:X:\MATLAB\R2010a\toolbox\compiler\deploy\win32 \MCRInstaller.exe(X是MATLAB安裝的盤符),如果你的電腦上安裝了MATLAB,則不需要在重新安裝這個軟件。另外,不同的 MATLAB版本提供的MATLAB Compiler Runtime可能會不同,如果在另一台電腦上自己編寫的軟件運行有問題,可能是編譯器的版本不同引起的