zoukankan      html  css  js  c++  java
  • 【原创】Matlab.NET混合编程技巧之直接调用Matlab内置函数

                  本博客所有文章分类的总目录:【总目录】本博客博文总目录-实时更新

          Matlab和C#混合编程文章目录 :【目录】Matlab和C#混合编程文章目录

      在我的上一篇文章【原创】Matlab.NET混编技巧之——找出Matlab内置函数中,已经大概的介绍了matlab内置函数在混合编程中的优点,并通过程序找出了matlab中的大部分内置函数,当然更多人关心是如何像我所说得那样,不用直接编译,就直接在C#中调用这些内置函数。本文就带你揭开这些谜团。

    声明,这篇文章是需要一点点混合编程基础的,基本概念和过程要懂一点,如果能简单成功混编一个简单的计算或者绘图例子,可以更容易理解。

    1.传统的Matlab.NET混合编程步骤

    传统的Matlab.NET混合编程有2种方式:

    1)Matlab编写好M函数,利用deploytool编译m函数生成dll,在C#项目中引用并调用;

    2)基于接口的编写方式,也是利用deploytool工具,过程繁琐一点,对编程人员素质要求高一点,但不需要进行繁琐的数据类型转换。我的博客有一篇文章专门介绍了这个混合编程方式,也有例子,大家有兴趣的可以看看:http://www.cnblogs.com/asxinyu/archive/2013/05/16/3082299.html

     不管上面用哪种方式,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:WorkDevelopMent_SVNMatlabMatlabBlogPlotTestsrc" "-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:WorkDevelopMent_SVNMatlabMatlabBlogPlotTest.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:WorkDevelopMent_SVNMatlabMatlabBlogPlotTest.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:WorkDevelopMent_SVNMatlabMatlabBlogPlotTestsrc" "-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:WorkDevelopMent_SVNMatlabMatlabBlogPlotTest.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:WorkDevelopMent_SVNMatlabMatlabBlogPlotTest.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:WorkDevelopMent_SVNMatlabMatlabBlogPlotTestsrc" "-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:WorkDevelopMent_SVNMatlabMatlabBlogPlotTest.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

  • 相关阅读:
    PAT (Advanced Level) 1080. Graduate Admission (30)
    PAT (Advanced Level) 1079. Total Sales of Supply Chain (25)
    PAT (Advanced Level) 1078. Hashing (25)
    PAT (Advanced Level) 1077. Kuchiguse (20)
    PAT (Advanced Level) 1076. Forwards on Weibo (30)
    PAT (Advanced Level) 1075. PAT Judge (25)
    PAT (Advanced Level) 1074. Reversing Linked List (25)
    PAT (Advanced Level) 1073. Scientific Notation (20)
    PAT (Advanced Level) 1072. Gas Station (30)
    PAT (Advanced Level) 1071. Speech Patterns (25)
  • 原文地址:https://www.cnblogs.com/asxinyu/p/DoNet_Invoke_Matlab_InvokeInLineFunction.html
Copyright © 2011-2022 走看看