簡析MATLAB和.NET混合編程

 

做者  Lemniscatejava

這個是我寫的一篇關於MATLAB課程的做業,做業已提交。因此,ChenGuangda老師看到了請不要覺得個人做業是從網上抄的,哈哈。程序員

0.背景

MATLAB做爲一款功能強大、效率高、交互性好的可視化高級計算機語言,在數值計算、自動控制、數字信號處理、圖形處理、仿真、神經網絡、小波分析等各個領域有着普遍的應用。雖然MATLAB是一個徹底獨立的編程和數據運算的集成環境使用它能夠很方便地作不少工做,可是,不少時候僅僅依靠MATLAB環境仍是不能很好地完成工做,例如一個大的項目中須要使用到MATLAB中很容易實現並且頗有些的功能時,若是這個時候使用特定語言開發,將會是一個費時費力的事情,並且穩定性、效率方面都不如MATLAB好;或者,其餘語言編寫的優秀程序,若是想在MATLAB中使用,就要重寫M文件,形成了人力和物力的浪費,因此MATLAB和其餘程序之間的數據交換就顯得十分必要,MATLAB程序接口的出現,就解決了這些問題,經過接口與其餘編程環境交互,各取所長,充分發揮MATLAB計算的優勢,而避開MATLAB效率低的問題。web

1.MATLAB的接口

       MATLAB提供了多種編程語言的接口,經過微軟的組建對象模型(Component Object ModelCOM)完成外部程序、客戶端和服務端之間的通信和數據共享,這些功能的實現都是使用了MATLAB的應用程序接口(Application Program InterfaceAPI)來實現的。算法

下圖是MATLAB提供的接口。編程

 

簡析MATLAB和.NET混合編程 - Castor - 趁年輕,多折騰~~
  MATLAB 使用自身強大的編譯器能夠將 MATLAB 的應用程序編譯爲一個獨立的程序 (.exe) 或者組件 (.dll) ,這些組件又可以被 Fortran C C++ 等高級語言調用,實現了和其餘程序之間的交互;經過使用 MATLAB Builder EX ,將 MATLAB 的函數打包爲組件,這樣就可以能被 Excel 使用;經過使用 MATLAB Builder JA ,能夠由 MATLAB 程序建立 Java 語言中的類,這些類徹底能夠在沒有安裝 MATLAB 的桌面計算機或者網絡服務器上運行。經過使用 MATLAB Builder NE ,將 MATLAB 函數封裝入 .NET 中類的方法,這些類就能夠像其餘託管代碼同樣被 .NET 環境下的全部語言調用,例如 C# VB.NET J# C++.NET F# 等語言,甚至是網絡程序也能夠調用,例如 ASP.NET

 

2.外部語言的選取

由上節可見MATLAB的編程接口是至關豐富的,這裏就.NET方式討論,使用.NET的接口有以下幾個優勢:數組

代碼安全。做爲託管代碼,不會出現指針帶來的問題,這就保證了程序的穩定性安全

容錯機制。C#中具備異常處理方法,所以即便程序在運行中出現了錯誤,也能從故障中快速恢復,或者提供較好的擺脫異常的方法,而不是像其餘程序那樣形成程序崩潰。服務器

面向對象。經過將函數打包爲一個類的方法,實現了完整的面向對象編程,方便了代碼的閱讀和管理,並可以實現面向對象中的重載、繼承、多態等功能。網絡

2.1什麼是.NET

       .NET的定義,根據微軟官方的描述:架構

       .NET is a "revolutionary new platform built on open Internet protocols and standards with tools and services that meld computing and communications in new ways".NET 是微軟公司的一組軟件技術,用來鏈接信息、人、系統和各類設備。它經過使用 Web Services 技術來得到軟件的高度集成。除了將小型的、分散的、構建模塊應用互相鏈接起來,還將 Internet 上的更大應用鏈接起來。微軟總裁兼首席執行官Steve Ballmer把它定義爲:.NET表明一個集合,一個環境,一個能夠做爲平臺支持下一代Internet的可編程結構。

       .NET的核心部分是.NET Framework,這是一組框架,是.NET的核心支持庫,.NET Framework提供CLR(公共語言運行時)提供了對各類程序的支持,一般將在CLR的控制下運行的代碼,稱爲託管代碼(managed code)。使用.NET開發的程序須要在.NET Framework下才能運行,就像VB的程序須要VB運行庫,java程序須要JVMJava虛擬機)同樣。下圖是.NET Framework的架構:

 

簡析MATLAB和.NET混合編程 - Castor - 趁年輕,多折騰~~
          經過使用 Visual Studio.NET 開發工具,可使用多種語言開發,採用 CLS (公共語言規範)後,編譯爲中間語言,這種語言是專門針對公共語言的,和其餘高級語言無關,所以,高級語言能夠在這個層面上實現融合和互通,這也是 .NET 架構的一大優點,也是其成功的關鍵因素。最後,在 CLR (公共語言運行時)提供的支持,從而在操做系統上運行。 MATLAB Builder NE 就是將 M 文件編譯爲位於 Basic Class Library 同一層,實現了程序的運行

 

2.2語言的選擇

       首先須要明白的是,NET Framework只是一個平臺,並非一種具體的編程語言,實際開發過程當中須要有一種具體的語言和對應的工具,根據微軟的構想,在推出.NET架構的同時,仍是推出了一款專門針對該平臺的語言——C#,該語言是純粹面向對象的,並能最大化地釋放.NET平臺的優點,實現了軟件的安全、快速開發。另外,根據上圖可知,使用的開發工具是Visual Studio.NET,微軟旗艦級的開發工具Visual Studio也升級到了2010版,該開發工具是一套可視化的編程環境,其強大的功能,如自動代碼、智能感知、錯誤高亮、代碼重構等功能,使程序開發起來事半功倍。

3.如何實現混合編程

       如前面所說,混合編程有一個很顯著的問題,就是最終的程序以何種方式實現。這涉及到了兩種實現方。首先,能夠將.NET程序在MATLAB中運行,這個時候MATLAB是宿主程序,而.NET程序以一種插件的方式存在,共享MATLAB的內存空間;另外一種方式是將NATLAB程序編譯爲託管代碼,而後在C#的程序中調用,這個時候就脫離了MATLAB的環境,能夠造成獨立的軟件。

3.1使用MATLAB.NET接口

這種方式是以MATLAB爲主程序,.NET程序以插件的方式爲MATLAB調用,該方法對MATLAB的要求很簡單,基本不須要作任何改動。事實上MATLAB自然的提供了對.NET程序的支持。

經過使用這種方式,能夠實現:1..NET中類的實例。2.經過使用類成員操做.NET程序。固然,這種方法和通常的面向對象仍是有一些侷限性,例如不能訪問子類,不能將.NET對象保存到MAT文件中,也不能使用控制檯輸入、輸出等。

事實上,使用這種方式開發的人員,更多的是.NET程序員,他們無需關心MATLAB是如何實現的,也用不着和MATLAB打交道,只須要在編程中可以將本身的接口暴露給MATLAB便可,固然了電腦上必須安裝.NET Framework才能實現。

下面是一個簡單的例子:

例如在MATLAB的命令窗口中輸入:

>> dt=System.DateTime(2011,5,11)

運行結果爲:

dt =

  System.DateTime

  Package: System

  Properties:

           Date: [1x1 System.DateTime]

            Day: 11

      DayOfWeek: [1x1 System.DayOfWeek]

      DayOfYear: 131

           Hour: 0

           Kind: [1x1 System.DateTimeKind]

    Millisecond: 0

         Minute: 0

          Month: 5

            Now: [1x1 System.DateTime]

         UtcNow: [1x1 System.DateTime]

         Second: 0

          Ticks: 634406688000000000

      TimeOfDay: [1x1 System.TimeSpan]

          Today: [1x1 System.DateTime]

           Year: 2011

       MinValue: [1x1 System.DateTime]

       MaxValue: [1x1 System.DateTime]

  Methods, Superclasses

       爲何是這個結果?首先,MATLAB在啓動的時候會自動加載程序集System.dll(另外一個是mscorlib.dll),該程序集是.NET中很是重要的文件之一,提供了基本類型、數學計算等功能。而DateTime就是其中的一個結構體,該結構體主要用於描述時間。使用該結構體建立了一個實例dt,而後調用的構造函數是DateTime(year,month,day)MATLAB顯示關於該實例的基本信息,並在最後還提供顯示該結構體方法和超類的連接。

若是再輸入:

>> dt.Year

則顯示:

ans =

        2011

       這裏就訪問了.NET代碼中的屬性。事實上,MATLAB提供了專門的函數查看託管類的屬性和方法。

例如輸入:

>> properties System.DateTime

>> methods System.DateTime

       就能夠查看一個結構體或者類支持的方法和屬性。

3.2如何開發自定義類

       雖然.NET提供了大量的類和方法,可是並不能知足實際工做中的須要,有時須要本身開發一些自定義的類,使用Visual Studio.NET將會很輕鬆地實現開發。

       VS中新建一個類庫的項目,在Class1.cs中輸入以下內容:

using System;

using System.Collections.Generic;

using System.Text;

using System.Windows.Forms;

namespace ToMATLAB

{

    public class XDClass

    {

        //這是一個不帶返回值的方法

        public void Message()

        {

            MessageBox.Show("Here is Dot Net~");

        }

       

        //這是一個屬性

        public string Help

        {

            get

            {

                return "I am a Property of Class XDClass";

            }

        }

        //這是一個帶返回值的方法,利用海倫公式計算三角形面積

        public double TriangleArea(double a,double b,double c)

        {

            double max = a;

            if (max < b) max = b;

            if (max < c) max = c;

            if (2 * max >= a + b + c)

                return -1;//不構成三角形

            else

            {

                double p = (a + b + c) / 2;

                return Math.Sqrt(p * (p - a) * (p - b) * (p - c));

            }

        }

    }

}

       而後按F6編譯生成一個名爲ToMATLAB.dll文件,該文件就是被MATLAB加載的.NET程序集。而後在MATLABCommand Window中輸入:

>> asmInfo = NET.addAssembly('C:\Users\Castor\Desktop\ToMATLAB.dll')

效果以下:

asmInfo =

  NET.Assembly handle

  Package: NET

Properties for class NET.Assembly:

    AssemblyHandle

    Classes

    Structures

    Enums

    GenericTypes

    Interfaces

    Delegates

NET.addAssembly函數加載一個.NET的程序集,即編譯生成的動態連接庫文件,加載完成後能夠經過Properties函數或者methods函數查看其屬性和方法。運行以下:

>> properties ToMATLAB.XDClass

Properties for class ToMATLAB.XDClass:

    Help

>> methods ToMATLAB.XDClass

Methods for class ToMATLAB.XDClass:

Equals Message       XDClass       eq            ge            le            notify

GetHashCode   ToString      addlistener   findobj       gt            lt           

GetType       TriangleArea  delete        findprop      isvalid       ne

       可見MATLAB可以識別咱們編寫的方法和屬性,下面測試一下屬性和方法:

>> xd=ToMATLAB.XDClass()

xd =

  ToMATLAB.XDClass handle

  Package: ToMATLAB

  Properties:

    Help: [1x1 System.String]

  Methods, Events, Superclasses

>> xd.Help

ans =

I am a Property of Class XDClass

>> xd.Message

>> xd.Message

xd.Message

>> xd.TriangleArea(3,4,5)

ans =

     6

>> xd.TriangleArea(3,4,1)

ans =

-1

當運行到Message的時候,會出現一個對話框:

 

簡析MATLAB和.NET混合編程 - Castor - 趁年輕,多折騰~~

這是使用了.NET中的MessageBox.Show方法的緣由,另外要注意的是,該對話框是有模式的對話框,這個時候編譯器會掛起,雖然在Command Window下能夠輸入命令,可是卻不能被編譯器解釋,這是模式對話框的一個顯著特色。最後調用了xd實例的方法,利用海倫公式計算一個三角形的面積,當提供的三個參數不能構成三角形的時候,計算結果爲-1,其實這個時候應該理解爲錯誤代碼,顯然面積應該是一個正數,經過檢查該值能夠判斷方法是否正確運行。

4.外部程序調用MATLAB函數

相比前一種方式,這種方法實施起來顯得有些複雜,可是可擴展更大,這種方式能夠徹底脫離MATLAB環境,實現軟件的快速開發。

在實施這一混合編程以前,須要先介紹獨立於MATLAB的程序一些基本問題的。

4.1 MCR簡介

 MCR的全稱是MATLAB Compiler Runtime,即MATLAB編譯器運行時。根據MathWorks公司的定義:

The MATLAB Compiler Runtime (MCR) is an execution engine made up of the same shared libraries MATLAB uses to enable the execution of MATLAB files on systems without an installed version of MATLAB.

可見MCR是一個由MATLAB共享類庫構成的執行引擎,他可以使MATLAB文件在沒有MATLAB的機器上運行。這一點和.NET Framework相對於.NET程序同樣,即爲程序的運行提供了底層支持。當發佈程序的時候,須要將MCR也打包進來,不然沒有MATLAB的機器上程序不能執行,如同.NET程序不能在沒有.NET Framework的機器上運行同樣。MCRMATLAB軟件一同發佈,能夠在MATLAB中輸入命令「mcr」或者「mcrinstaller」獲取其保存路徑:

>> mcr

The WIN32 MCR Installer, version 7.14, is:

    D:\MATLAB\toolbox\compiler\deploy\win32\MCRInstaller.exe

MCR installers for other platforms are located in:

    D:\MATLAB\toolbox\compiler\deploy\<ARCH>

  <ARCH> is the value of COMPUTER('arch') on the target machine.

Full list of available MCR installers:

D:\MATLAB\toolbox\compiler\deploy\win32\MCRInstaller.exe

For more information, read your local MCR Installer help.

Or see the online documentation at The MathWorks' web site. (Page may load slowly.)

根據上面的運行結果,可知該文件的完整路徑是:

D:\MATLAB\toolbox\compiler\deploy\win32\MCRInstaller.exe

4.2 MWArray API簡介

 MCR包含了文件MWArray.dll,該文件中的API承擔了用戶程序和MCR之間數據交換的任務,所以,每個獨立文件都須要包含對該文件的引用,不然程序就不能使用MATLAB中的函數,爲使用該文件,須要先安裝MCR,該文件在安裝完MCR後位於:installation_folder\toolbox\dotnetbuilder\bin\architecture\framework_version

另外,該文件中有兩個重要的命名空間,MathWorks.MATLAB.NET.ArraysMathWorks.MATLAB.NET.UtilityArrays命名空間下的類提供從其餘任何兼容CLSCommon Language Specification 語言訪問MATLAB中數組的功能,這些類支持數組格式化、類型的特定索引和錯誤處理的功能。而Utility命名空間下的類提供了對MWArray類架構和MATLAB公共運行時的託管API的通用支持。

4.3.混合編程的實施

爲了將MATLAB中的程序做爲組件提供給其餘.NET程序使用,須要作兩方面的工做:

1.M文件打包爲與.NET兼容的程序集

2.在外部程序中添加對程序集的引用

4.3.1 MATLAB端的工做

首先是將M文件打包爲程序集。MATLAB將函數做爲某個類中的方法,經過對類的操做實現對函數的調用。首先準備好函數,這些函數須要保存在M文件中,例如MATLAB中的函數SVD很強大,而咱們不想本身重寫,或者對幻方比較感興趣,也不知道具體如何事實,可是在MATLAB下面只要一個函數就能解決,這些功能對外部程序就頗有用,下面是這兩個M文件:

%函數1.矩陣的SVD分解

function [u,s,v]=XDSVD(A)

    [u,s,v]=svd(A);

end

 

%函數2.生成幻方矩陣

function m=XDMagic(n)

    m=magic(n);

end

假設這兩個文件分別保存爲XDSVD.mXDMagic.m,下面將其打包爲.NET兼容的組件。這就須要使用deploytool命令:

MATLAB的命令窗口中輸入:

>> deploytool

將出現以下對話框,設置好項目名,並指定目標組件的形式是 .NET Assembly ,而後肯定。
  簡析MATLAB和.NET混合編程 - Castor - 趁年輕,多折騰~~
        Deployment Tool 中添加一個名爲 Functions 的類,併爲該類添加咱們事先準備好的兩個 M 文件。

 

簡析MATLAB和.NET混合編程 - Castor - 趁年輕,多折騰~~

  這個時候XDMagicXDSVD函數將做爲Functions類的方法而存在,這個時候就能夠點擊開始編譯了,不過在編譯以前,還須要說說Package標籤下的一些細節。

 

簡析MATLAB和.NET混合編程 - Castor - 趁年輕,多折騰~~
          由上圖可見,該標籤頁下會顯示編譯以後的文件,下方還有一個連接是 Add MCR ,該功能是將 MCRInstaller.exe 也做爲程序的組件打包進去,若是使用這個方式,編譯程序會變得很大(不添加才 1KB ,若是添加會變爲 173MB ),會顯著增長編譯時間,實際上更好的方法是,不添加 MCR ,而是另外單獨拷貝,這樣部署起來更方便靈活。

 

       編譯完成以後或生成一個和項目同名的文件夾,其中最重要的文件就是distrib文件夾下的Castor.dll,該文件就是提供給其餘.NET程序調用的類庫。經過反編譯程序能夠查看它的成員方法,以下圖:

 

簡析MATLAB和.NET混合編程 - Castor - 趁年輕,多折騰~~
  4.3.2 .NET主程序編程

接下來的工做就是如何在外部程序中使用該程序集。仍是以C#爲例,建立一個Windows窗口程序。添加必須的控件,而後添加對MWArray.dllCastor.dll的引用以及加入須要的命名空間。

程序界面以下:

 

簡析MATLAB和.NET混合編程 - Castor - 趁年輕,多折騰~~ 簡析MATLAB和.NET混合編程 - Castor - 趁年輕,多折騰~~

核心代碼以下:

private void button1_Click(object sender, EventArgs e)

{

    Functions f = new Functions();

    MWNumericArray na = null;

    MWArray[] arr1 = null;

    MWArray[] arr2 = null;

    int i = Convert.ToInt16(textBox2.Text);

    arr1 = f.XDMagic(1, i);

    try

    {

        arr2 = f.XDSVD(3, arr1[0]);//返回三個數組

        MessageBox.Show(arr2[0].ToString(), "矩陣U");

        MessageBox.Show(arr2[1].ToString(), "矩陣S");

        MessageBox.Show(arr2[2].ToString(), "矩陣V");

    }

    catch (Exception exc)

    {

        MessageBox.Show("出現異常,緣由是:" + exc.Message, "錯誤", MessageBoxButtons.OK, MessageBoxIcon.Error);

    }

}

private void button2_Click(object sender, EventArgs e)

{

    Functions f = new Functions();

    MWNumericArray na = null;

    MWArray[] ansArray = null;

    int i = Convert.ToInt16(textBox2.Text);

    ansArray=f.XDMagic(1,i);

    na = (MWNumericArray)ansArray[0];//只有一個數組返回

    MessageBox.Show(na.ToString());

}

4.3 調試運行

程序運行效果以下(假設輸入的參數是5):

幻方:

 

簡析MATLAB和.NET混合編程 - Castor - 趁年輕,多折騰~~

  矩陣USV分別以下:

 

簡析MATLAB和.NET混合編程 - Castor - 趁年輕,多折騰~~
簡析MATLAB和.NET混合編程 - Castor - 趁年輕,多折騰~~ 
簡析MATLAB和.NET混合編程 - Castor - 趁年輕,多折騰~~
          這個結果和 MATLAB 下運行的效果是同樣的。最後提一下一個小問題,就是程序在初始化自定義類 Functions 時會花費較多時間,大約持續 2~3 秒鐘,程序如同假死通常,但第二次點擊按鈕反應卻很快,能夠推斷程序集是動態加載的。

 

5.總結

       經過對MATLAB混合編程環境的論述和實例講解,闡述了.NETMATLAB交互使用的方法,縮短了項目開發的週期,提升了算法的準確度,具備很重要的實踐意義。

 

轉自  http://379910987.blog.163.com/blog/static/3352379720116151449673/?suggestedreading&wumii

相關文章
相關標籤/搜索