C# 调用MatLab引擎 - 小众知识

C# 调用MatLab引擎

2013年01月27日 14:18:05 苏内容
  标签: C#/MatLab
阅读:7328

编译环境:c#,xp系统,Matlab6.5

新建一个窗体项目,添加matlab引用。

然后试了四种方式调用matlab:

第一种

  1. MLApp.MLAppClass matlab = new MLApp.MLAppClass();  
  2. matlab.Visible = 1;  
  3. matlab.Execute("figure(1)");  

 

第二种

  1. MLApp.DIMLApp matlab = null;  
  2. Type matlabAppType = System.Type.GetTypeFromProgID("Matlab.Application");  
  3. matlab = System.Activator.CreateInstance(matlabAppType) as MLApp.DIMLApp;  
  4. matlab.Visible = 1;  
  5. matlab.Execute("figure(2)");  

 

第三种

  1. MLApp.MLApp matlab = null;  
  2. Type matlabAppType = System.Type.GetTypeFromProgID("Matlab.Application");  
  3. matlab = System.Activator.CreateInstance(matlabAppType) as MLApp.MLApp;  
  4. matlab.Visible = 1;  
  5. matlab.Execute("figure(3)");  

 

第四种

  1. MLApp.MLApp matlab = new MLApp.MLApp();  
  2. matlab.Visible = 1;  
  3. matlab.Execute("figure(4)"); 


     

    四种情况在本机上均可启动matlab

    然后把生成的程序copy到(包括Interop.MLApp.dll)

    1,xp系统,matlab2009a

    发现第一和第四种方式运行会报错,第二和第三种可以启动matlab。

    这MLApp.MLAppClass, MLApp.DIMLApp,MLApp.MLApp三者的区别我不晓得,杯具。

    2,win7系统,matlab2009a

    结果同1。

    编译环境:c#,win7系统,Matlab2009

    四种调用方式不变,在本机上均可运行

    然后把生成的程序copy到(包括Interop.MLApp.dll)

     

    1,xp系统,matlab6.5

    发现第一和第四种方式运行会报错,第二和第三种可以启动matlab。

    2,xp系统,matlab2009a

    四种情况在本机上均可启动matlab

    结论:为了避免matlab版本问题,最好使用第二和第三种方法。

    C#调用Matlab 引擎


    在C#中调用Matlab, 需要先配置一下Matlab编译器, 然后在VS里面引用Matlab组件
    具体操作如下:

    在VS里面引用Matlab组件
    引用   .Net MWArray API (不是必须)
    引用Matlab Application Type Library


    using MathWorks;
    using MathWorks.MATLAB;
    using MathWorks.MATLAB.NET.Arrays;
    using MathWorks.MATLAB.NET.Utility;
    using MLApp;
    private void button1_Click(object sender, EventArgs e)
        {
            MLApp.MLAppClass matlab = new MLApp.MLAppClass();
            string command;
            command = "t=2:0.2:4*pi;y=sin(t);plot(t,y)";
          
            matlab.Visible = 1;         
            matlab.Execute(command);     // 执行Matlab命令
            command = @"print(gcf,   '-djpeg',   'c:\Test1')";     // 保存图片
            matlab.Execute(command);
            matlab.Quit();
            matlab = null;
            pictureBox1.Image = Image.FromFile(@"c:\Test1.jpg");   
        }


    以上网上转载的用c#调用matlab的另外一种方法,为什么用lm算法训练BP网络的代码运行时就不能跳出仿真图,换其他函数就都可以。各位高手帮忙指点下迷津。
    private void Form1_Load(object sender, EventArgs e)
        {
            MLAppClass matlab = new MLAppClass();
            string command = "P=[21 23;12 43;23 15;]" +
            "I=[12;23;45];" +
            "P=P';" +
            "I=I';" +
            "save data P I;" +
            "[Pn,minp,maxp,In,mint,maxt] = premnmx(P,I)" +
        
            "net=newff(minmax(Pn),[10,1],{'tansig', 'purelin'},'trainbr');" +
          
            "net=init(net)" +
            "net.trainParam.show=100; %两次显示之间的训练步数" +
            "net.trainParam.lr=0.3;%学习速率" +
            "net.trainParam.epochs=10000; %训练次数" +
            "net.trainParam.goal=0.000001;%训练目标" +
            "[net,tr]=train(net,Pn,In);" +
            "Inputweights=net.IW{1,1}" +
            "Inputbias=net.b{1}" +
            "Layerweights=net.LW {2,1}" +
            "Layerbias=net.b{2}"+
              "figure(gcf)";

            matlab.Visible = 1;
            matlab.Execute(command);
            matlab.Quit();
            matlab = null;
            }

      }



    1.确保本机安装MatLab

    2.C#程序中添加对Matlab的引用 安装目录下的MWArray.dll

    3.创建MatLab 对象 MLApp.MLApp matlab=null;

    Type matlabAppType=System.Type.GetTypeFormProgID("Matlab.Application");

    matlab=System.Activator.CreateInstance(matlabAppType) as MLApp.MLApp;

    4. 指定matlab执行m文件的路径

    预先写好的m文件存在本地目录下,当前存在程序执行目录下

    string command=string.Emptry;//定义命令行要执行的字符串

    string path_project=Directory.GetCurrentDirectory(); 获取当前的文件目录

    string path_matlab="cd(' "+path_project+" ') ";

    matlab.visible=0; 隐藏matlab 执行窗口

    matlab.Execute(path_matlab);

    matlab.Execute("clear  all");//清空上次执行结果,否则会报错

    command=@"a=eg_Sum("+parameter+")"; parameter为m文件的参数

    matlab.Execute(command);//执行命令行调用m文件并传参

    object result=matlab.GetVariable("a","base");

    object[,]  arraryResult=result as object[,]


    调用matlab全程采用元胞数组进行传参

    对输出的结果可以用二维数组进行处理


    实验室需要,继续在Win下面给Matlab作包装,写一些GUI什么的,之前也弄过一些相关的东西。主要采用的MFC加Matlab的方式,

    想把GUI做的更好看一些,打算换一种方式尝试一下。具体的方式主要有m文件作成库文件,Matlab Engine等等,对Engine方式做

    一些简单的总结。

     添加Matlab Engine的步骤

    1.加入引用

    Matlab Application  Type Library这个选项

     

    2.添加引擎变量

    MLApp.MLApp matlab = new MLApp.MLApp(); 

    matlab就是需要的引擎对象
    本质上主要的数据接口就是 C#数据 -->  Matlab ---> C#环境

    接口变量是 System.Array变量,主要函数如下

     http://www.mathworks.cn/cn/help/matlab/call-matlab-com-automation-server.html

    控制台范例如下

    using System;namespace ConsoleApplication4
    {class Class1
    {
        [STAThread]    static void Main(string[] args)
        {
            MLApp.MLApp matlab = new MLApp.MLApp(); 
    
            System.Array pr = new double[4];
            pr.SetValue(11,0);
            pr.SetValue(12,1);
            pr.SetValue(13,2);
            pr.SetValue(14,3);
    
            System.Array pi = new double[4];
            pi.SetValue(1,0);
            pi.SetValue(2,1);
            pi.SetValue(3,2);
            pi.SetValue(4,3);
    
            matlab.PutFullMatrix("a", "base", pr, pi);
    
            System.Array prresult = new double[4];
            System.Array piresult = new double[4];
    
            matlab.GetFullMatrix("a", "base", ref prresult, ref piresult);
            }
        }
    }

     

    注意:

    GetFullMatrix函数后两个参数分别为, 实数部分的数值, 复数部分的数值, 类似 a + bi, 分别存入两个数组中

    如果Matlab环境中只有实数部分的数值, 如此返回会出现运行时异常

    可以采用另外一种方式

    GetWorkspaceData函数,将数值存入object对象当中,例如

    matlab.GetWorkspaceData("varName", "base", out targetInCsharp);

    返回到object对象当中,再进行进一步操作

    解决了数据传输问题,

    那么可以将C#中的数据读入以后传入到Matlab环境当中,再将结果从Matlab环境中读出,更多信息,

    参见Matlab官方文档

    http://www.mathworks.cn/cn/help/matlab/external-interfaces.html

     

    使用GetWorkspaceData的例子

    读取的数据返回到 object对象中, 采用out方式

                MLApp.MLApp matlab = new MLApp.MLApp();
                matlab.Execute("cd " + matlabWorkPath);            object result;
                matlab.Execute("load matlab.mat");
                matlab.GetWorkspaceData("b", "base", out result);            double[,] d = (double[,])result;
                Console.WriteLine(d[0, 0].ToString());

     写入到matlab的workspace当中

                double[,] dd = new double[1, 5];            for (int i = 5; i > 0; i--)
                {
                    dd[0, 5 - i] = i; 
                }            object outArray = (object)dd;
                matlab.PutWorkspaceData("b", "base", outArray);



    C#使用Matlab集锦


    1.安装使用matlab



    关于matlab与c#之间一些数据类型的转换的方法,总结一下,最主要的是要完成下面几个步骤:

    1、同时安装.netframwork与MCR(matlab compile runtime)。这个在装完vs.net与matlab以后,前面2个组件也就安装好了。

    2、利用matlab自带的.nettool工具将.m文件转换成.net组件--->.dll文件为接口,它实际上不含任何实现,都是调用另一个.ctf文件来完成具体的功能。

    3、在c#中,必须引入mwarray.dll才能拥有在.net中进行矩阵运算所需要的一切。虽然matlab help中只是说推荐,但一般的应用中,只是进行一部分函数的调用,而不是去取得整个运行结果。这个.dll是必须引入的。有时mclmcrrt74.dll这个文件也需要引入。根据具体的要求,需要引入的文件也有所差别。

    4、生成一个实例,并对.net组件所输出的结果进行数据类型的转换,以符合.net编程环境中对数据类型的要求,这个在以前我已经讲过,这里就不再多说了。关键是掌握如何把一个矩阵(在matlab中,一个m*n的矩阵对应.net中的一个1*(m*n)的数组)转换成数据类型一致的数组。目前所有的matlab数据类型(无论什么类型,都可以把它看成一个矩阵,这样就可以利用数组的思想来思考)都可以进行转化,具体的可能需要经过实验才能符合各自的要求。

    虽然matab对.net的支持不如它对c++支持的功能强大,但也已经满足了我们实际应用的需求。如果我们可以把大部分的运算都放在matlab里面完成,数据转换的数量又少,那么整个系统的运行速度与效率还是挺高的。 
    [http://blog.csdn.net/lemonfamily/archive/2007/01/29/1497527.aspx]


    2.使用
    装matlab ,添加引用[VB。Net]
      Matlab   =   CreateObject("matlab.application")   
      MatLab.MinimizeCommandWindow()   
      strMatLab   =   "t=2:0.2:4*pi;y=sin(t);plot(t,y)"     //这只不过是一个例子,求特征值的string要自己查   
      MatLab.Execute(strMatLab)   
    [http://topic.csdn.net/t/20040621/19/3111008.html]


    3.矩阵转换示例


    用于将matlab的返回值矩阵传递到C#规范的矩阵中
     
    MWArray[] ResOut = null; //用于值输出的matlab矩阵
    ResOut=GTN.GetMatchNo(1,MainAdd, ModelAdd, FName.GTM(), Vaval);
    MWNumericArray temp = (MWNumericArray)ResOut[0]; 
    //矩阵转换
    Array  netInterfaceMatrix = temp.ToArray(MWArrayComponent.Real); //c#规范的矩阵
    double[,] location = (double[,])netInterfaceMatrix; //变态的强制类型转换
    [http://mibxue.spaces.live.com/blog/cns!1B1AC4E08A659077!1836.entry]



    4.心得等
    最近在搞matlab与c#混合编程,发现了一些问题,说出来大家讨论一下:
    (1) matlab中的乘幂运算是非常好用的,但变成com组件后被C#调用起来真是问题多多,我现在束手无策。c#不支持sqrt的写法,连'^'后面是小数都会抛出异常,真是让人郁闷。
    (2)matlab中的画图功能在c#能得到很好的应用。
    (3)做成的com组件不论是在matlab中生成还是在c#中的初始化都比较耗时间。
    所以建议大家在这两者混合编程时,尽量考虑清楚那部分功能在那个程序中实现,而不是一股脑的将计算功能交给matlab,将GUI功能交给c#,这样不仅使程序非常臃肿,而且耗时耗力,出力不讨好。

    -------
    我实在不甘心自己写的一堆matlab程序就这样白白泡汤了,自己又重新想了一下,经过测试我的想法是可行的。
    1   matlab中的乘幂运算在c#中的解决方法:
        (1)乘幂计算的原始matlab函数是power(x,y),在c#中的函数是Math.Pow(x,y),所以可以将matlab中的乘幂运算  (是指幂不是整数时)统统写成power(x,y)形式。
    缺点:程序写起来和c#一样很麻烦,而且matlab7.4a也没有向c#中的函数提示功能,郁闷ing
        (2)若matlab程序中改动太多且不好改时,可以将乘幂运算交给c#。
    2  matlab传参数给c#时,若是复数是一定要注意用MWComplex class,否则返回的参数是null,传过来的参数根本没法用

    [http://www.chinavib.com/space/html/99/t-52999.html]


    4.类似软件
    Matlab,Mathmatica,Maple,的Mathmatica 一些比较研究[http://www.cnblogs.com/ericguo/archive/2005/02/05/102628.html]


    Donet 下的矩阵类库
    文章http://kenwell.org/blog/article.asp?id=135   下载http://kenwell.ustc.googlepages.com/rtwmatrix_src.rar 


     

    发表于 2007-11-20 11:07 kevin 阅读(1449) 评论(7)  编辑 收藏 所属分类: 技术及文章推介 、软件技术小文 
     
     
    评论 
    #1楼 [楼主] 
    补充: 
    2.c#.net下实现调用 
    打开或新建一个c#项目(我采用的是vs.net编辑器),选中右边的解决方案资源管理器中的引用,点鼠标右键,选添加引用,在弹出来的窗口中选com,然后也找到comtest_1_0.dll,点选择,然后确定就可,此时此com组件也添加到工程里面去了,同样我们可以选择对象浏览器来看comtest及下面的sgltest类,c#测试项目如下: 
    测试im_test方法的代码: 
    comtest.sgltestClass st=new comtest.sgltestClass(); 
    st.im_test(); 
    测试split2rgb方法的代码: 
    comtest.sgltestClass st=new comtest.sgltestClass(); 
    object h=null,w=null,r=null,g=null,b=null; 
    object filename="c:\\1.jpg"; 
    st.split2rgb(5,ref h,ref w,ref r,ref g,ref b,filename); 
    可见输入参数是ref object型的,而输出参数是object型的,测试同样大获成功,与matlab下运行的结果一摸一样,爽呆了。 

    [http://hi.baidu.com/redtramp/blog/item/785997264e4d27148b82a1c1.html]
    kevin       评论于 2007-11-20 11:34    回复  引用  查看    
    #2楼 [楼主] 
    Matlab统计工具箱简介 
    http://www.chinavib.com/space/html/68/t-53768.html
    kevin       评论于 2007-11-20 11:39    回复  引用  查看    
    #3楼 [楼主] 
    matlab里把图像图形嵌入到excel和word中的方法 
    http://www.chinavib.com/space/html/17/t-53717.html
    kevin       评论于 2007-11-20 11:41    回复  引用  查看    
    #4楼 [楼主] 

    在.NET中应用MATLAB算法 
    http://bbs.zdnet.com.cn/viewthread.php?tid=119499 

    在科学研究和工程应用中,往往要进行大量的数学计算,其中包括矩阵运算。这些运算一般来说难以用手工精确和快捷地进行,而要借助计算机编制相应的程序做近似计算。目前流行用Basic、Fortran和c语言编制计算程序, 既需要对有关算法有深刻的了解,还需要熟练地掌握所用语言的语法及编程技巧。对多数科学工作者而言,同时具备这两方面技能有一定困难。通常,编制程序也是繁杂的,不仅消耗人力与物力,而且影响工作进程和效率。为克服上述困难,美国Mathwork公司于1967年推出了“Matrix Laboratory”(缩写为MATLAB)软件包,并不断更新和扩充。目前最新的6.x版本(windows环境)是一种功能强、效率高便于进行科学和工程计算的交互式软件包。其中包括:一般数值分析、矩阵运算、数字信号处理、建模和系统控制和优化等应用程序,并集应用程序和图形于一便于使用的集成环境中。在此环境下所解问题的MATLAB语言表述形式和其数学表达形式相同,不需要按传统的方法编程。不过,MATLAB作为一种新的计算机语言,要想运用自如,充分发挥它的威力,也需先系统地学习它。但由于使用MATLAB编程运算与人进行科学计算的思路和表达方式完全一致,所以不象学习其它高级语言--如Basic、Fortran和C等那样难于掌握。实践证明,你可在几十分钟的时间内学会MATLAB的基础知识,在短短几个小时的使用中就能初步掌握它.从而使你能够进行高效率和富有创造性的计算。 MATLAB大大降低了对使用者的数学基础和计算机语言知识的要求,而且编程效率和计算效率极高,还可在计算机上直接输出结果和精美的图形拷贝,所以它的确为一高效的科研助手。自推出后即风行美国,流传世界。 
    MATLAB算法是一个优秀的算法,我们在软件开发过程中,尤其是数据库开发方面,要进行数据汇总、统计分析、然后根据汇总的数据产生图表(包括柱图、饼图、四分图、雷达图等),这种需求甚为普遍。 
    由于MATLAB算法具有强大的计算处理功能,所以在许多软件中已经用到它,比如作个销售预测,前提是基于以往的销售数据,可以用MATLAB算法对以往的销售数据进行处理(如函数、矩阵的一系列运算,或者采用一些运筹学的知识进行数据处理),再由MATLAB算法产生出相关数据的精美图形输出,得到一个具有科学理论依据的方案,把我们的管理思想融合到了计算机程序设计中,使软件解决方案不是简单的电算化工具,而是一个综合许多学科的智慧的结晶! 
    微软的.NET开发工具,结合数据库SQL SERVER,是开发数据库应用的最佳选择!我们可以把SQL SERVER里的数据用MATLAB算法进行处理,还可以将自己写的算法包装成COM,在.NET中引用就可以了。在使用的MATLAB算法时,图形输出的功能往往被人忽略,下面的例子,就是采用的MATLAB出的图形

    首先在.NET中,引用matlab 的对象库(Matlab Application(version 6.5) Type Library),笔者采用的是MATLAB 6.5 版本,然后在窗体上加一个图片框PictureBox1,用于显示图片; 
    一个Button1用于调用MATLAB,并加载图形。 

    代码: 

    Dim strMatLab As String '定义matlab语句字符串 
    ' 显示正弦图 
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click 
    Dim MatLab As Object 
    '建立matlab应用 
    MatLab = CreateObject("matlab.application") 
    '最小化matlab命令窗口 
    MatLab.MinimizeCommandWindow() 
    'matlab语句 
    strMatLab = "t=2:0.2:4*pi;y=sin(t);plot(t,y)" 
    '执行matlab算法 
    matlab.Execute(strMatLab) 
    '生成一个JPG的图形c:\Test1.jpg 
    matlab.Execute("print( gcf, '-djpeg', 'c:\Test1')") 
    '退出matlab,释放资源 
    matlab.Quit() 
    MatLab = Nothing 
    '显示在图片框 
    PictureBox1.Image = New Bitmap("c:\Test1.jpg") 
    End Sub 

    ' 显示饼图 
    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click 
    Dim matlab As Object 
    matlab = CreateObject("matlab.application") 
    strMatLab = "sale=[100 400 150 250 500];pie3(sale,[0 0 1 0 0],{'公司A','公司B','公司C','公司D','公司E'})" 
    matlab.Execute(strMatLab) 
    matlab.Execute("print( gcf, '-djpeg', 'c:\Test2')") 
    matlab.Quit() 
    matlab = Nothing 
    PictureBox1.Image = New Bitmap("c:\Test2.jpg") 
    End Sub 

    ' 显示三维螺旋线图 
    Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click 
    Dim matlab As Object 
    matlab = CreateObject("matlab.application") 
    strMatLab = "t=0:0.2:4*pi;plot3(sin(t),cos(t),t)" 
    matlab.Execute(strMatLab) 
    matlab.Execute("print( gcf, '-djpeg', 'c:\Test3')") 
    matlab.Quit() 
    matlab = Nothing 
    PictureBox1.Image = New Bitmap("c:\Test3.jpg") 
    End Sub 

    ' 显示立体波浪图 
    Private Sub Button5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button5.Click 
    Dim matlab As Object 
    matlab = CreateObject("matlab.application") 
    strMatLab = "[X,Y,Z] = peaks(20);surfc(X,Y,Z);colormap hsv;axis ([-2 4 -6 8 -10 6])" 
    matlab.Execute(strMatLab) 
    matlab.Execute("print( gcf, '-djpeg', 'c:\Test5')") 
    matlab.Quit() 
    matlab = Nothing 
    PictureBox1.Image = New Bitmap("c:\Test5.jpg") 
    End Sub 

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load 
    PictureBox1.SizeMode = PictureBoxSizeMode.StretchImage 
    End Sub 
    总结:一般情况下,我们将自己的算法在MATLAB中生成dll,供VB.NET调用此算法,输入一组数据,输出一系列数据,而且MATLAB算法比较简单,一个命令就完成了许多功能,大大提高了开发效率! 








    kevin       评论于 2007-11-20 14:12    回复  引用  查看    
    #5楼 [楼主] 
    .Net下矩阵类库 
    http://d.download.csdn.net/down/210979/logxing
    kevin       评论于 2007-11-20 15:43    回复  引用  查看    
    #6楼 [楼主] 

    关于MATLAB和c#混合编程以及如何打包的 文章指数:0 CSDN Blog推出文章指数概念,文章指数是对Blog文章综合评分后推算出的,综合评分项分别是该文章的点击量,回复次数,被网摘收录数量,文章长度和文章类型;满分100,每月更新一次。

    从本周一到现在,主要完成了两个任务。

    主要是完成这么一个构架 matlab m文件 + framwork2.0 + vs2005(c# winform)

    这个构架师没有问题的

    第一个任务:如何在vs 2005对winfom 程序打包 ,打包后在目标机器上自动检测安装framwork2.0 ,在“开始”菜单中卸载应用程序

    第二个任务: 含有m文件做成的dll组件如何在目标机器上使用,经过查询资料,得知需要安装MATLAB Componet runtime 编译器。

    这个安装程序的名字为MCRinstaller.exe



    发布到目标机器的时候,vs2005打包的安装程序和MCRinstaller.exe都要在目标机器上安装。

    from:http://blog.csdn.net/bailuotuo/archive/2008/02/28/2127157.aspx
    kevin       评论于 2008-02-28 18:56    回复  引用  查看    
    #7楼  
    请较楼主一个问题,在用matlab R2007b,vs2005混合编程过程中,用matlab生成dll文件没有报错,可是在vs2005调用dll文件时出现:Error: System.Runtime.InteropServices.COMException (0x80004005): Data conversion 
    error: Unsupported VARIANT type 
    在 PlotDemoComp.PlotterClass.drawgraph(Object coords) 
    在 MathWorks.Demo.PlotDemoApp.PlotDemoApp.Main(String[] args) 位置 D:\PlotExa 
    mple\PlotDemoCSharpApp\PlotDemoApp.cs:行号 54 
    -------------------------------------------------------------------------- 
    请问是什么问题引起的啊? 
    谢谢。。。。。。。。。。。。。。。


    扩展阅读