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

  • 相关阅读:
    网站名记录
    Unity 之 图片显示的真实大小
    Unity 之 Time
    数据库死锁分析与解决
    使用命令远程注销服务器
    Web自动化测试框架改进
    Tomcat 性能监控及调优
    移动互联网安全性测试技术简介
    白盒测试中如何实现真正意义上并发测试(Java)
    接口性能测试方案 白皮书 V1.0
  • 原文地址:https://www.cnblogs.com/asxinyu/p/DoNet_Invoke_Matlab_InvokeInLineFunction.html
Copyright © 2011-2022 走看看