1.传统的Matlab.NET混合编程步骤
传统的Matlab.NET混合编程有2种方式:
1)Matlab编写好M函数,利用deploytool编译m函数生成dll,在C#项目中引用并调用;
2)基于接口的编写方式,也是利用deploytool工具,过程繁琐一点,对编程人员素质要求高一点,但不需要进行繁琐的数据类型转换。
不管上面用哪种方式,Matlab和C#混编的基本步骤,大概都是下面的过程:
1) 编写M函数,并首先在Matlab中测试是正确可以调用的。注意命名规范,注释规范;
2) 使用命令打开 deploytool工具,设置项目名称,选择类型:.NET Assembly,然后新建一个类,并添加编写好的M函数
3) 编译,生成dll,并在C#项目中添加引用(还需要引用对应版本的MWArray),利用对象浏览器查看生成dll的方法结构,并根据Matlab和C#的类型转换规则,进行数据转换即可, 如果是接口的编程,这个过程相对要简单。
2.深入解析传统混编所生成的代码
2.1 第一步:编写M函数,并测试可以使用
为了好我们今天的目的相匹配,特意封装一个简单的内置函数,plot,来画一个简单的图形,如下所示M函数
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 }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 }对比大家就可以发现,只不过一个更加傻瓜化,参数都是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次绘制的效果。分别截图如下:
共同學習,寫下你的評論
評論加載中...
作者其他優質文章
