本博客所有文章分類的總目錄:http://www.cnblogs.com/asxinyu/p/4288836.html
Matlab和C#混合編程文章目錄 :http://www.cnblogs.com/asxinyu/p/4329753.html
如果這些文章對你有用,有幫助,期待更多開源組件介紹,請不要吝嗇手中的鼠標。
時間:2013年4月21日,5月5日例子Demo測試成功
1.前言
Matlab Builder NE 工具箱是與C#混編的工具箱,里面的幫助文檔很詳細,提供了4種情況下與.NET混合編程的案例。
1.是簡單的組件集成,通過Matlab生成Dll程序集,在.NET環境中,通過MWArray組件來調用;
2.還有一個是在Web環境下使用Figure和混編的情況,與1比較類似;
3.另外一個就是我們今天要講到的基於類型安全的接口編程,以及對WCF和MEF的支持;
4.最后一個是在.NET Remoting技術中的使用。
在初級入門教程中,以及我現在的混編開發中,都只是用到了第1個方法,和很簡單,也很快,當然要你掌握了很多基礎技術之后才能達到這個水平。今天要見到的基於接口的編程,有一個很大的好處就是可以避免類型轉換,因為之前的方法都有大量的.NET和Matlab類型進行轉換,基礎不扎實的朋友很容易搞混淆。而基於接口的編程,則可以避免很多問題,但同時也對基礎提出了更高的要求,要對接口定義,作用,以及方法多態等面向對象的特性更加了解。
下面截圖是在Matlab幫助的說明:

2.Type-Safe Interfaces簡單說明
與直接編譯為.NET程序集的要求不同,使用這項技術對.NET程序員的要求小很多,只需要很少的Matlab知識,但要對.NET技術精通,
之前由於Matlab的數據類型和.NET的基本數據類型不兼容,所以為了使得Matlab和.NET程序進行數據通信,就需要使用下面的技術:
1)Marshal data from .NET input data to a deployed function by creating an MWArray object from native .NET data.
The public functions in a deployed component return MWArray objects.
2)Marshal the output MATLAB data in an MWArray into native .NET data by calling one of the MWArray marshaling methods (ToArray(), for example).
所以使用傳統的混編方式,又很多數據類型轉換的過程。而在使用Type-Safe Interfaces技術后,這些中間過程都可以忽略,
只需要關系輸入的.NET類型以及輸出的.NET類型結果,Matlab會對數據進行內部的轉換處理。可以看看前后2副圖的對比:

因此,我們可以很明顯的看到Type-Safe Interfaces帶來的優勢:
You avoid training and coding costs associated with teaching end users to work with MWArrays.
You minimize cost of data you must marshal by either placing MWArray objects in type-safe interfaces or by calling MWArray-based functions in the deployed component.
Flexibility — you mix type-safe interfaces with manual data marshaling to accommodate data of varying sizes and access patterns.
For example, you may have a few large data objects (images, for example) that would incur excess cost to your organization if managed
with a type-safe interface. By mixing type-safe interfaces and manual marshaling, smaller data types can be managed
automatically with the type-safe interface and your large data can be managed on an as-needed basis.
3.Type-Safe Interfaces實際案例
對這個混編方式,很顯示可以節省很多事情,我認為,作為原始的數據類型轉換方式,還是應該掌握的。在掌握了之后,再使用這個方法,會事半功倍,畢竟不是所有的問題都可以用接口解決。接下來,就讓我們一起用一個小的編程實例,來演示整個過程的使用。
演示環境:Visual Studio 2010,Matlab 2012a,.NET 4.0
演示內容:一個簡單的乘法運算混編實現
一、新建一個 類庫類型的項目 ,名稱MatlabDemo,.NET 4.0,如下圖所示:

一、在上面的項目中添加一個接口文件IMultiply.cs,並編寫下面的代碼,因為我們實現的是一個簡單的乘法,所以添加如下幾個接口方法:
1 namespace MatlabDemo 2 { 3 /// <summary>乘法接口</summary> 4 public interface IMultiply 5 { 6 //2個數直接相乘 7 double multiply(double x, double y); 8 9 //數組相乘 10 double[] multiply(double[] x, double y); 11 12 //矩陣相乘 13 double[,] multiply(double[,] x, double[,] y); 14 } 15 }
這里注意,一定要將接口的可訪問性設置為Public,否則混編的時候,Matlab會找不到接口原型,編譯失敗。編寫好,編譯項目即可,會在bin文件夾下得到MatlabDemo.dll文件,這個文件下面的步驟會用到。
三、編寫M函數,並設置混編項目。我們編寫一個簡單的乘法M函數m,如下所示:
1 function z = multiply(x, y) 2 3 z = x * y;
注意這里的名稱一定要和接口方法的名稱對於起來,否則Matlab怎么會認識,想想就明白了。然后在Matlab中輸入deploytool命令,輸入項目名稱:TypeSaftDemo,並選擇項目類型:.NET Assembly,這個過程是“混編三部曲”基本過程,以前的視頻中專門見到了,不仔細說明,如下圖所示:

確定之后,混編項目基本就建立了,然后新建一個類DemoTest,並把上面編寫的multiply.m函數添加到這個類中去,這其實就是一個常規的混編過程,很簡單。添加完成之后,如果是普通的混編方式,直接編譯就可以了,但基於接口的混編方式,還有一個過程要設置,看下圖,單擊混編項目的設置(Settings...):

如下圖,打開設置后,選擇“Type Safe API”選項卡:
首先,選擇我們在第一個過程中編寫好的MatlabDemo.dll接口文件,選擇后,程序會自動搜索該dll中的可用接口(公開的),在.NET interface下拉列表中顯示,選擇你需要的,這里我們是IMultiply,如下圖所示的MatlabDemo.IMultiply,然后選擇該接口和Matlab混編程序中對於的類,我們的multiply.m函數在DemoTest類中,如下圖的Wrapped class:

設置完成之后,關閉即可。然后編譯,如果沒有問題,提示編譯成功之后,打開編譯好的文件夾,我們可以看到如下3個dll文件:

生成的3個文件,TypeSafeDemo.dll其實和普通的混編方式是一樣的,可以和以前數據類型轉換的方式一樣使用;而DemoTestIMultiply.dll和TypeSafeDemoNative.dll這2個一起使用,Matlab已經在內部將數據轉換過程封裝好了,直接使用即可。第一種方式就不演示了,直接演示如何用接口來計算乘法。
五、C#調用混編好的dll計算結果。在上一節中我們已經說明了幾個dll的作用,下面將演示他們的用法,將DemoTestIMultiply.dll和TypeSafeDemoNative.dll一起復制到測試項目的C#項目中去(新建一個控制台測試項目),分別添加這幾個dll的引用:MWAarray.dll和DemoTestIMultiply.dll以及TypeSafeDemoNative.dll。然后添加命名空間,具體核心代碼如下所示:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 using MathWorks.MATLAB.NET.Arrays; 7 using MathWorks.MATLAB.NET.Utility; 8 9 using TypeSaftDemo; 10 11 namespace TypeSaftTest 12 { 13 class Program 14 { 15 static void Main(string[] args) 16 { 17 //混編接口類的實例化 18 DemoTestIMultiply di = new DemoTestIMultiply(); 19 double[,] a = new double[2,2] {{1,2},{3,4} }; 20 double[,] b = new double[2, 2] { { 6, 7 }, {8, 9 } }; 21 //分別演示接口的3種不同調用 22 var t1 = di.multiply(3, 5); 23 var t2 = di.multiply(new double[] { 1, 2, 3 }, 5); 24 var t3 = di.multiply(a, b); 25 Console.WriteLine("2個數直接相乘:"+t1.ToString()); 26 Console.Write("數組與單個數直接相乘:"); 27 foreach (var item in t2 ) Console.Write(item.ToString()+" "); 28 Console.WriteLine(); 29 Console.Write("矩陣乘法:"); 30 foreach (var item in t3) Console.Write(item.ToString() + " "); 31 Console.ReadKey (); 32 } 33 } 34 }
結果如下圖所示:

上面就是Matlab和C#基於接口的混合編程的詳細過程,混編是一個很有用的工具,但要用好,其實真的很難,接觸混編這么長的時間以來,碰到過很多同學使用這個工具,絕大部分是誤用,導致無故的工作量。要想混編成為自己工作和學習的得力助手,必須加強Matlab和.NET基礎的學習,只有2者的基礎掌握好了,足夠熟悉這2個平台,你才可能更順利的解決混編過程中遇到的問題。當混編出了問題的時候,需要很多經驗才能度過難關,這一點很重要,不要指望學會這個過程,就可以解決所有問題。期待Mathworks公司對Matlab的混編編程支持越來越強大。
4.相關資源
1 Matlab Builder NE具箱的User’s Guide欄目中的Type-Safe Interfaces, WCF, and MEF
2 Loren Shure 博客:
http://blogs.mathworks.com/loren/2011/06/03/introducing-type-safe-apis-with-builder-ne/
