Matlab.NET混合編程技巧之——直接調用Matlab內置函數(附源碼)

原文: 【原創】Matlab.NET混合編程技巧之——直接調用Matlab內置函數(附源碼)

在個人上一篇文章【原創】Matlab.NET混編技巧之——找出Matlab內置函數中,已經大概的介紹了matlab內置函數在混合編程中的優勢,並經過程序找出了matlab中的大部份內置函數,固然更多人關心是如何像我所說得那樣,不用直接編譯,就直接在C#中調用這些內置函數。本文就帶你揭開這些謎團。html

聲明,這篇文章是須要一點點混合編程基礎的,基本概念和過程要懂一點,若是能簡單成功混編一個簡單的計算或者繪圖例子,能夠更容易理解。web

1.傳統的Matlab.NET混合編程步驟

傳統的Matlab.NET混合編程有2種方式:編程

1)Matlab編寫好M函數,利用deploytool編譯m函數生成dll,在C#項目中引用並調用;windows

2)基於接口的編寫方式,也是利用deploytool工具,過程繁瑣一點,對編程人員素質要求高一點,但不須要進行繁瑣的數據類型轉換。個人博客有一篇文章專門介紹了這個混合編程方式,也有例子,你們有興趣的能夠看看:http://www.cnblogs.com/asxinyu/archive/2013/05/16/3082299.html瀏覽器

 無論上面用哪一種方式,Matlab和C#混編的基本步驟,大概都是下面的過程: app

1) 編寫M函數,並首先在Matlab中測試是正確能夠調用的。注意命名規範,註釋規範; ide

2) 使用命令打開 deploytool工具,設置項目名稱,選擇類型:.NET Assembly,而後新建一個類,並添加編寫好的M函數 函數

3) 編譯,生成dll,並在C#項目中添加引用(還須要引用對應版本的MWArray),利用對象瀏覽器查看生成dll的方法結構,並根據Matlab和C#的類型轉換規則,進行數據轉換便可, 若是是接口的編程,這個過程相對要簡單。工具

2.深刻解析傳統混編所生成的代碼

2.1 第一步:編寫M函數,並測試可使用

爲了好咱們今天的目的相匹配,特地封裝一個簡單的內置函數,plot,來畫一個簡單的圖形,以下所示M函數    post

1 function PlotTest(n)
2 %編寫一個簡單的函數,對plot進行簡單封裝一下
3 plot(1:n,1:n);
4 %測試正確,才能夠進行下一步工做

注意,混編必須是m函數function的形式才能被調用。上述函數簡單測試一下,沒有問題(複雜的函數必定要多測試,不然後續調試很是困難)。繼續下一步。

2.2 第二步:在Matlab中使用deploytool創建混編項目

 在Matlab工做區輸入命令:deploytool,而後獲得下面界面,輸入混編項目的名稱,選擇存儲位置,關鍵的是類型那裏必定要選擇".NET Assembly"。以下圖所示:

選擇「OK」以後,下一步matlab界面右側會出現項目解決方案,須要添加類名稱和M文件。這個類名稱,就是編譯完成以後C#項目中的類對象名稱,而後添加咱們剛纔上一步編寫的「PlotTest.m」,而後編譯便可,以下圖所示:

到此爲止,一個常規 簡單的Matlab.NET混編已經完成了60%了。編譯完成以後,打開「Package」選項卡,便可看到生成的dll文件,而後點擊右鍵,打開文件夾便可,以下圖所示:

2.3 查看混編生成的代碼

  這個過程很關鍵,其實包含不少信息,只不過95%以上的人都沒有注意到其實混編生成的dll是有源文件的,經過查看源文件就應該知道混編的原理,只不過這是matlab自動生成 而已。那看看生成的源碼吧。

  打開Matlab混編項目的目錄,能夠看到有2個文件夾,"distrib」,「src」2個文件夾。"distrib"文件夾就是上面圖中生成的dll,注意有2個dll,1個是「項目名稱.dll」,一個是「項目名稱Native.dll」,這2個dll的差異能夠經過"distrib"文件夾源碼來觀察。「distrib」就是源代碼的文件夾。以下圖所示,src文件夾的文件示意圖:

 咱們2.2中新建的類名是TestDemo,因此生成的的源碼名稱也是TestDemo,看看這2個cs文件中的代碼,同時類的方法也能夠在VS中經過對象瀏覽器來查看dll有哪些方法以及方法的參數類型。直接貼這2個cs文件的代碼,順便解釋和對比下:

TestDemo.cs文件源碼:

  1 /*
  2 * MATLAB Compiler: 4.17 (R2012a)
  3 * Date: Mon Sep 09 16:19:01 2013
  4 * Arguments: "-B" "macro_default" "-W" "dotnet:PlotTest,TestDemo,0.0,private" "-T"
  5 * "link:lib" "-d" "D:\Work\DevelopMent_SVN\Matlab\MatlabBlog\PlotTest\src" "-w"
  6 * "enable:specified_file_mismatch" "-w" "enable:repeated_file" "-w"
  7 * "enable:switch_ignored" "-w" "enable:missing_lib_sentinel" "-w" "enable:demo_license"
  8 * "-v" "class{TestDemo:D:\Work\DevelopMent_SVN\Matlab\MatlabBlog\PlotTest.m}" 
  9 */
 10 using System;
 11 using System.Reflection;
 12 using System.IO;
 13 using MathWorks.MATLAB.NET.Arrays;
 14 using MathWorks.MATLAB.NET.Utility;
 15 
 16 #if SHARED
 17 [assembly: System.Reflection.AssemblyKeyFile(@"")]
 18 #endif
 19 
 20 namespace PlotTest
 21 {
 22 
 23   /// <summary>
 24   /// The TestDemo class provides a CLS compliant, MWArray interface to the M-functions
 25   /// contained in the files:
 26   /// <newpara></newpara>
 27   /// D:\Work\DevelopMent_SVN\Matlab\MatlabBlog\PlotTest.m
 28   /// <newpara></newpara>
 29   /// deployprint.m
 30   /// <newpara></newpara>
 31   /// printdlg.m
 32   /// </summary>
 33   /// <remarks>
 34   /// @Version 0.0
 35   /// </remarks>
 36   public class TestDemo : IDisposable
 37   {
 38     #region Constructors
 39 
 40     /// <summary internal= "true">
 41     /// The static constructor instantiates and initializes the MATLAB Compiler Runtime
 42     /// instance.
 43     /// </summary>
 44     static TestDemo()
 45     {
 46       if (MWMCR.MCRAppInitialized)
 47       {
 48         Assembly assembly= Assembly.GetExecutingAssembly();
 49 
 50         string ctfFilePath= assembly.Location;
 51 
 52         int lastDelimiter= ctfFilePath.LastIndexOf(@"\");
 53 
 54         ctfFilePath= ctfFilePath.Remove(lastDelimiter, (ctfFilePath.Length - lastDelimiter));
 55 
 56         string ctfFileName = "PlotTest.ctf";
 57 
 58         Stream embeddedCtfStream = null;
 59 
 60         String[] resourceStrings = assembly.GetManifestResourceNames();
 61 
 62         foreach (String name in resourceStrings)
 63         {
 64           if (name.Contains(ctfFileName))
 65           {
 66             embeddedCtfStream = assembly.GetManifestResourceStream(name);
 67             break;
 68           }
 69         }
 70         mcr= new MWMCR("",
 71                        ctfFilePath, embeddedCtfStream, true);
 72       }
 73       else
 74       {
 75         throw new ApplicationException("MWArray assembly could not be initialized");
 76       }
 77     }
 78 
 79 
 80     /// <summary>
 81     /// Constructs a new instance of the TestDemo class.
 82     /// </summary>
 83     public TestDemo()
 84     {
 85     }
 86 
 87 
 88     #endregion Constructors
 89 
 90     #region Finalize
 91 
 92     /// <summary internal= "true">
 93     /// Class destructor called by the CLR garbage collector.
 94     /// </summary>
 95     ~TestDemo()
 96     {
 97       Dispose(false);
 98     }
 99 
100 
101     /// <summary>
102     /// Frees the native resources associated with this object
103     /// </summary>
104     public void Dispose()
105     {
106       Dispose(true);
107 
108       GC.SuppressFinalize(this);
109     }
110 
111 
112     /// <summary internal= "true">
113     /// Internal dispose function
114     /// </summary>
115     protected virtual void Dispose(bool disposing)
116     {
117       if (!disposed)
118       {
119         disposed= true;
120 
121         if (disposing)
122         {
123           // Free managed resources;
124         }
125 
126         // Free native resources
127       }
128     }
129 
130 
131     #endregion Finalize
132 
133     #region Methods
134 
135     /// <summary>
136     /// Provides a void output, 0-input MWArrayinterface to the PlotTest M-function.
137     /// </summary>
138     /// <remarks>
139     /// M-Documentation:
140     /// 編寫一個簡單的函數,對plot進行簡單封裝一下
141     /// </remarks>
142     ///
143     public void PlotTest()
144     {
145       mcr.EvaluateFunction(0, "PlotTest", new MWArray[]{});
146     }
147 
148 
149     /// <summary>
150     /// Provides a void output, 1-input MWArrayinterface to the PlotTest M-function.
151     /// </summary>
152     /// <remarks>
153     /// M-Documentation:
154     /// 編寫一個簡單的函數,對plot進行簡單封裝一下
155     /// </remarks>
156     /// <param name="n">Input argument #1</param>
157     ///
158     public void PlotTest(MWArray n)
159     {
160       mcr.EvaluateFunction(0, "PlotTest", n);
161     }
162 
163 
164     /// <summary>
165     /// Provides the standard 0-input MWArray interface to the PlotTest M-function.
166     /// </summary>
167     /// <remarks>
168     /// M-Documentation:
169     /// 編寫一個簡單的函數,對plot進行簡單封裝一下
170     /// </remarks>
171     /// <param name="numArgsOut">The number of output arguments to return.</param>
172     /// <returns>An Array of length "numArgsOut" containing the output
173     /// arguments.</returns>
174     ///
175     public MWArray[] PlotTest(int numArgsOut)
176     {
177       return mcr.EvaluateFunction(numArgsOut, "PlotTest", new MWArray[]{});
178     }
179 
180 
181     /// <summary>
182     /// Provides the standard 1-input MWArray interface to the PlotTest M-function.
183     /// </summary>
184     /// <remarks>
185     /// M-Documentation:
186     /// 編寫一個簡單的函數,對plot進行簡單封裝一下
187     /// </remarks>
188     /// <param name="numArgsOut">The number of output arguments to return.</param>
189     /// <param name="n">Input argument #1</param>
190     /// <returns>An Array of length "numArgsOut" containing the output
191     /// arguments.</returns>
192     ///
193     public MWArray[] PlotTest(int numArgsOut, MWArray n)
194     {
195       return mcr.EvaluateFunction(numArgsOut, "PlotTest", n);
196     }
197 
198 
199 
200     /// <summary>
201     /// This method will cause a MATLAB figure window to behave as a modal dialog box.
202     /// The method will not return until all the figure windows associated with this
203     /// component have been closed.
204     /// </summary>
205     /// <remarks>
206     /// An application should only call this method when required to keep the
207     /// MATLAB figure window from disappearing.  Other techniques, such as calling
208     /// Console.ReadLine() from the application should be considered where
209     /// possible.</remarks>
210     ///
211     public void WaitForFiguresToDie()
212     {
213       mcr.WaitForFiguresToDie();
214     }
215 
216 
217 
218     #endregion Methods
219 
220     #region Class Members
221 
222     private static MWMCR mcr= null;
223 
224     private bool disposed= false;
225 
226     #endregion Class Members
227   }
228 }
View Code

TestDemoNative.cs文件源碼:

  1 /*
  2 * MATLAB Compiler: 4.17 (R2012a)
  3 * Date: Mon Sep 09 16:19:01 2013
  4 * Arguments: "-B" "macro_default" "-W" "dotnet:PlotTest,TestDemo,0.0,private" "-T"
  5 * "link:lib" "-d" "D:\Work\DevelopMent_SVN\Matlab\MatlabBlog\PlotTest\src" "-w"
  6 * "enable:specified_file_mismatch" "-w" "enable:repeated_file" "-w"
  7 * "enable:switch_ignored" "-w" "enable:missing_lib_sentinel" "-w" "enable:demo_license"
  8 * "-v" "class{TestDemo:D:\Work\DevelopMent_SVN\Matlab\MatlabBlog\PlotTest.m}" 
  9 */
 10 using System;
 11 using System.Reflection;
 12 using System.IO;
 13 using MathWorks.MATLAB.NET.Arrays;
 14 using MathWorks.MATLAB.NET.Utility;
 15 
 16 #if SHARED
 17 [assembly: System.Reflection.AssemblyKeyFile(@"")]
 18 #endif
 19 
 20 namespace PlotTestNative
 21 {
 22 
 23   /// <summary>
 24   /// The TestDemo class provides a CLS compliant, Object (native) interface to the
 25   /// M-functions contained in the files:
 26   /// <newpara></newpara>
 27   /// D:\Work\DevelopMent_SVN\Matlab\MatlabBlog\PlotTest.m
 28   /// <newpara></newpara>
 29   /// deployprint.m
 30   /// <newpara></newpara>
 31   /// printdlg.m
 32   /// </summary>
 33   /// <remarks>
 34   /// @Version 0.0
 35   /// </remarks>
 36   public class TestDemo : IDisposable
 37   {
 38     #region Constructors
 39 
 40     /// <summary internal= "true">
 41     /// The static constructor instantiates and initializes the MATLAB Compiler Runtime
 42     /// instance.
 43     /// </summary>
 44     static TestDemo()
 45     {
 46       if (MWMCR.MCRAppInitialized)
 47       {
 48         Assembly assembly= Assembly.GetExecutingAssembly();
 49 
 50         string ctfFilePath= assembly.Location;
 51 
 52         int lastDelimiter= ctfFilePath.LastIndexOf(@"\");
 53 
 54         ctfFilePath= ctfFilePath.Remove(lastDelimiter, (ctfFilePath.Length - lastDelimiter));
 55 
 56         string ctfFileName = "PlotTest.ctf";
 57 
 58         Stream embeddedCtfStream = null;
 59 
 60         String[] resourceStrings = assembly.GetManifestResourceNames();
 61 
 62         foreach (String name in resourceStrings)
 63         {
 64           if (name.Contains(ctfFileName))
 65           {
 66             embeddedCtfStream = assembly.GetManifestResourceStream(name);
 67             break;
 68           }
 69         }
 70         mcr= new MWMCR("",
 71                        ctfFilePath, embeddedCtfStream, true);
 72       }
 73       else
 74       {
 75         throw new ApplicationException("MWArray assembly could not be initialized");
 76       }
 77     }
 78 
 79 
 80     /// <summary>
 81     /// Constructs a new instance of the TestDemo class.
 82     /// </summary>
 83     public TestDemo()
 84     {
 85     }
 86 
 87 
 88     #endregion Constructors
 89 
 90     #region Finalize
 91 
 92     /// <summary internal= "true">
 93     /// Class destructor called by the CLR garbage collector.
 94     /// </summary>
 95     ~TestDemo()
 96     {
 97       Dispose(false);
 98     }
 99 
100 
101     /// <summary>
102     /// Frees the native resources associated with this object
103     /// </summary>
104     public void Dispose()
105     {
106       Dispose(true);
107 
108       GC.SuppressFinalize(this);
109     }
110 
111 
112     /// <summary internal= "true">
113     /// Internal dispose function
114     /// </summary>
115     protected virtual void Dispose(bool disposing)
116     {
117       if (!disposed)
118       {
119         disposed= true;
120 
121         if (disposing)
122         {
123           // Free managed resources;
124         }
125 
126         // Free native resources
127       }
128     }
129 
130 
131     #endregion Finalize
132 
133     #region Methods
134 
135     /// <summary>
136     /// Provides a void output, 0-input Objectinterface to the PlotTest M-function.
137     /// </summary>
138     /// <remarks>
139     /// M-Documentation:
140     /// 編寫一個簡單的函數,對plot進行簡單封裝一下
141     /// </remarks>
142     ///
143     public void PlotTest()
144     {
145       mcr.EvaluateFunction(0, "PlotTest", new Object[]{});
146     }
147 
148 
149     /// <summary>
150     /// Provides a void output, 1-input Objectinterface to the PlotTest M-function.
151     /// </summary>
152     /// <remarks>
153     /// M-Documentation:
154     /// 編寫一個簡單的函數,對plot進行簡單封裝一下
155     /// </remarks>
156     /// <param name="n">Input argument #1</param>
157     ///
158     public void PlotTest(Object n)
159     {
160       mcr.EvaluateFunction(0, "PlotTest", n);
161     }
162 
163 
164     /// <summary>
165     /// Provides the standard 0-input Object interface to the PlotTest M-function.
166     /// </summary>
167     /// <remarks>
168     /// M-Documentation:
169     /// 編寫一個簡單的函數,對plot進行簡單封裝一下
170     /// </remarks>
171     /// <param name="numArgsOut">The number of output arguments to return.</param>
172     /// <returns>An Array of length "numArgsOut" containing the output
173     /// arguments.</returns>
174     ///
175     public Object[] PlotTest(int numArgsOut)
176     {
177       return mcr.EvaluateFunction(numArgsOut, "PlotTest", new Object[]{});
178     }
179 
180 
181     /// <summary>
182     /// Provides the standard 1-input Object interface to the PlotTest M-function.
183     /// </summary>
184     /// <remarks>
185     /// M-Documentation:
186     /// 編寫一個簡單的函數,對plot進行簡單封裝一下
187     /// </remarks>
188     /// <param name="numArgsOut">The number of output arguments to return.</param>
189     /// <param name="n">Input argument #1</param>
190     /// <returns>An Array of length "numArgsOut" containing the output
191     /// arguments.</returns>
192     ///
193     public Object[] PlotTest(int numArgsOut, Object n)
194     {
195       return mcr.EvaluateFunction(numArgsOut, "PlotTest", n);
196     }
197 
198 
199     /// <summary>
200     /// Provides an interface for the PlotTest function in which the input and output
201     /// arguments are specified as an array of Objects.
202     /// </summary>
203     /// <remarks>
204     /// This method will allocate and return by reference the output argument
205     /// array.<newpara></newpara>
206     /// M-Documentation:
207     /// 編寫一個簡單的函數,對plot進行簡單封裝一下
208     /// </remarks>
209     /// <param name="numArgsOut">The number of output arguments to return</param>
210     /// <param name= "argsOut">Array of Object output arguments</param>
211     /// <param name= "argsIn">Array of Object input arguments</param>
212     /// <param name= "varArgsIn">Array of Object representing variable input
213     /// arguments</param>
214     ///
215     [MATLABSignature("PlotTest", 1, 0, 0)]
216     protected void PlotTest(int numArgsOut, ref Object[] argsOut, Object[] argsIn, params Object[] varArgsIn)
217     {
218         mcr.EvaluateFunctionForTypeSafeCall("PlotTest", numArgsOut, ref argsOut, argsIn, varArgsIn);
219     }
220 
221     /// <summary>
222     /// This method will cause a MATLAB figure window to behave as a modal dialog box.
223     /// The method will not return until all the figure windows associated with this
224     /// component have been closed.
225     /// </summary>
226     /// <remarks>
227     /// An application should only call this method when required to keep the
228     /// MATLAB figure window from disappearing.  Other techniques, such as calling
229     /// Console.ReadLine() from the application should be considered where
230     /// possible.</remarks>
231     ///
232     public void WaitForFiguresToDie()
233     {
234       mcr.WaitForFiguresToDie();
235     }
236 
237 
238 
239     #endregion Methods
240 
241     #region Class Members
242 
243     private static MWMCR mcr= null;
244 
245     private bool disposed= false;
246 
247     #endregion Class Members
248   }
249 }
View Code

對比你們就能夠發現,只不過一個更加傻瓜化,參數都是Object了,其實這樣反而很差,增長了類型轉換的代價,若是知道,爲什麼不給一個正確的給他呢。關於這2個dll的速度,曾經據說過是有差異的,博客園有人給過測試,我沒實際測試過,仍是習慣用傳統的TestDemo.cs,由於參數類型都是Object,不直觀,出了問題也有點頭疼。

2.4 上述Matlab自動生成代碼的要點

  後面某些類或者方法的XML註釋就不說了,自動生成的東西,能夠對照M文件的註釋來看。

1.首先看第一段的註釋信息:

 1 /*
 2 * MATLAB Compiler: 4.17 (R2012a)
 3 * Date: Mon Sep 09 16:19:01 2013
 4 * Arguments: "-B" "macro_default" "-W" "dotnet:PlotTest,TestDemo,0.0,private" "-T"
 5 * "link:lib" "-d" "D:\Work\DevelopMent_SVN\Matlab\MatlabBlog\PlotTest\src" "-w"
 6 * "enable:specified_file_mismatch" "-w" "enable:repeated_file" "-w"
 7 * "enable:switch_ignored" "-w" "enable:missing_lib_sentinel" "-w" "enable:demo_license"
 8 * "-v" "class{TestDemo:D:\Work\DevelopMent_SVN\Matlab\MatlabBlog\PlotTest.m}" 
 9 */
10 using System;
11 using System.Reflection;
12 using System.IO;
13 using MathWorks.MATLAB.NET.Arrays;
14 using MathWorks.MATLAB.NET.Utility;

上面這段信息主要是說明當前Matlab編譯器的版本,由於編譯的版本和部署的MCR版本必須對應起來,不然是不能運行的。而後有編譯日期,以及編譯的參數,類名以及M函數的地址等信息,其實知道這些參數,理論上是能夠本身在程序裏面調用Matlab的編譯器進行編譯工做的,只不過比較複雜,能力有限,研究不下去。下面的引用你們應該明白,這個是MWArray.dll裏面的命名空間,因此混編的項目都要引用對應版本的MWArray.dll

2.關鍵的靜態構造函數

 1 static TestDemo()
 2     {
 3       if (MWMCR.MCRAppInitialized)
 4       {
 5         Assembly assembly= Assembly.GetExecutingAssembly();
 6         string ctfFilePath= assembly.Location;
 7         int lastDelimiter= ctfFilePath.LastIndexOf(@"\");
 8         ctfFilePath= ctfFilePath.Remove(lastDelimiter, (ctfFilePath.Length - lastDelimiter));
 9         string ctfFileName = "PlotTest.ctf";
10         Stream embeddedCtfStream = null;
11         String[] resourceStrings = assembly.GetManifestResourceNames();
12         foreach (String name in resourceStrings)
13         {
14           if (name.Contains(ctfFileName))
15           {
16             embeddedCtfStream = assembly.GetManifestResourceStream(name);
17             break;
18           }
19         }
20         mcr= new MWMCR("",ctfFilePath, embeddedCtfStream, true);
21       }
22       else
23       {
24         throw new ApplicationException("MWArray assembly could not be initialized");
25       }
26     }

  若是有一些C#的開發和編程經驗看上面的代碼問題應該不大,不然還真有點難說清楚,簡單的說幾個要點:

  1)這個構造函數的做用主要是檢測MCR對象是否初始化,若是沒有,則尋找程序集,並拼接資源的位置,正確進行初始化

  2) 上面的ctf實際上是包含在dll程序集裏面的,以資源的形式,這個文件是核心,它才真正的包括了Matlab編譯以後的,MCR能夠運行的中間程序。

  3) 必需要合法正確的ctf文件和dll文件才能 正確的初始化mcr對象,合法的意思,是Matlab內部有校驗機制,包括對相關版本,在之前的版本生成文件中,很明顯,如今2012a裏面都隱藏起來了,不過要求都同樣。

  4) 上面方法其實已經間接的告訴了咱們怎麼初始化mcr對象,有了mcr對象,一切都好辦了,由於它纔是MCR的核心。 

3.PlotTest封裝的方法代碼

 1     public void PlotTest()
 2     {
 3       mcr.EvaluateFunction(0, "PlotTest", new MWArray[]{});
 4     }
 5     public void PlotTest(MWArray n)
 6     {
 7       mcr.EvaluateFunction(0, "PlotTest", n);
 8     }
 9     public MWArray[] PlotTest(int numArgsOut)
10     {
11       return mcr.EvaluateFunction(numArgsOut, "PlotTest", new MWArray[]{});
12     }
13     public MWArray[] PlotTest(int numArgsOut, MWArray n)
14     {
15       return mcr.EvaluateFunction(numArgsOut, "PlotTest", n);
16     }

  看了字段代碼,再對應mcr的初始化,其實都很明朗了。經過mcr的EvaluateFunction來調用M函數。上面的代碼有幾個重載方法,能夠實用不少不一樣的狀況,有時候,這些方法的個數會更多,其實沒多大必要,也能夠本身編譯一下,把沒用的刪掉,保留少數幾個有用的便可。同時也能夠看到,這裏直接經過字符串來傳遞函數名稱的,所以必須保證這個函數能被mcr搜索到。好比咱們這裏的"PlotTest"這個函數其實就包含了ctf文件中(注意ctf文件是能夠和dll分開的,在混編項目裏能夠設置)。  

3.上述代碼到內置函數的調用

   上述已經講解了整個mcr調用的過程,其實就是經過mcr的EvaluateFunction來調用M函數,但要保證對於的函數名稱在mcr搜索的範圍內。那麼咱們是否是能夠假設:內置函數都在MCR內部,應該是能夠搜索到的,那麼把上面的函數名稱換一下,是否是也是可行的。這個假設也是我最先接觸時候的想法,有了假設,固然要去驗證。如今看來這個固然是確定的,那麼不妨從新演示一遍。過程不詳細講了,代碼也有註釋,混編要引用的MWArray.dll和命名空間也不提了,看代碼:

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Reflection;
 6 using System.IO;
 7 
 8 using MathWorks.MATLAB.NET.Utility;
 9 using MathWorks.MATLAB.NET.Arrays;
10 
11 
12 namespace BuildInFunctionDemo
13 {
14     class Program
15     {
16         static MWMCR mcr;
17         static void Main(string[] args)
18         {
19             #region 首先使用PlotTest.dll來初始化mcr,由於這個dll是混編「合法」產生的,只有這樣才能順利啓動mcr
20             if (MWMCR.MCRAppInitialized)
21             {
22                 string path = Path.Combine(System.Environment.CurrentDirectory, "PlotTest.dll");
23                 Assembly assembly = Assembly.LoadFile(path);
24                 string ctfFilePath = assembly.Location;
25                 int lastDelimiter = ctfFilePath.LastIndexOf(@"\");
26                 ctfFilePath = ctfFilePath.Remove(lastDelimiter, (ctfFilePath.Length - lastDelimiter));
27                 string ctfFileName = "PlotTest.ctf";
28                 Stream embeddedCtfStream = null;
29                 String[] resourceStrings = assembly.GetManifestResourceNames();
30 
31                 foreach (String name in resourceStrings)
32                 {
33                     if (name.Contains(ctfFileName))
34                     {
35                         embeddedCtfStream = assembly.GetManifestResourceStream(name);
36                         break;
37                     }
38                 }
39                 mcr = new MWMCR("",ctfFilePath, embeddedCtfStream, true);
40             }
41             else
42             {
43                 throw new ApplicationException("MWArray assembly could not be initialized");
44             }
45             #endregion
46 
47             #region 直接調用混編dll中的封裝函數進行測試
48             mcr.EvaluateFunction(0, "PlotTest", 5);
49 
50             //注意這裏要斷點調試才能看到效果哦,由於mcr會把圖繪製在一個Figure上面,
51             //後面的會覆蓋前面的,這裏暫停一下,能夠看前面的效果
52             //下面就是直接調用matlab的plot函數的效果
53             MWNumericArray x = new double[]{1,2,3,4,5};
54             MWNumericArray y = new double[]{2,1,2.8,5.3,4.7};
55             mcr.EvaluateFunction(0, "plot",x,y );
56             #endregion
57 
58             Console.ReadKey();
59         }
60     }
61 }

惟一要注意的就是50-52的說明,要加斷點看2次繪製的效果。分別截圖以下:

4.總結

  拋磚引玉,這裏只是一個思路,附代碼下載吧。

   http://www.kuaipan.cn/file/id_4279479643944070.htm

相關文章
相關標籤/搜索