C++中调用Matlab库函数

在上一篇关于调用MatLab数学函数库的日志中,基本上只说了一件事情:MatLab的底部数学计算引擎其实都是一些C++函数库,这些函数库被编译成了C++动态链接库(也就是在安装目录下的bin\win32文件夹中的那些.dll文件),我们可以直接来调用这些存在于.dll文件中的函数,而与MatLab运行环境无关。当然,这样做,可能会觉得有点儿盗窃的感觉,不过,可以肯定的是,这不是盗窃,这是合法的(因为这个函数库向外公开,也是MatLab产品的一部份,公司还为这个专门出了文档。可是,好像7.0以后的版本就没有这么好的事儿了)。
   在这里又多了一种语言——“C#”。主要是因为如果要开发一个软件,那么,在现在这个时代里,用C++来做界面显示,实在是一种非常不可取的事情。虽然也用VC6.0的MFC来开发过软件,但现在想想还是很后怕的。而C#做界面显示和整个程序的架构就显得非常的简单方便了。所以,我的想法是这样的:在C++中调用MatLab数学库中的函数(我真的是把绝大多数的数值计算都压到MatLab 身上了)包装成我自己的数学计算库,然后再在C#中调用我自己的数学计算库中的数值算法。这个过程,开始的时候我也不知道能不能成功,后来经过不断的尝试发现是可行的。下面就举一个完整例子写到下面,因为我非常害怕自己会忘掉。
   就举一个LU分解解一次方程组的例子吧:
  1、安装MatLab6.5主要是为了得到MatLab数学库的头文件.dll文件和.lib文件,当然可以从其它电脑上把包含这些文件的文件夹拷过来用,具体是哪些文件夹,后面会说到。
  2、启动VC6.0,新建一个工程,新建的时候选“工程”页中的"Win32 Dynamic-Link Library",表示要建一个动态链接库项目。
  3、建好了.dll(Dynamic-Link Library的简称)项目之后,首先要做就是进行包含目录设置:“工具”—>“先项”—>“目录”—>“目录[S]”在这个下接框中选“Include files”项进行头文件库设置,在下面的文本框中输入要需要的头文件的所在的文件夹目录(这样设置之后,在需要的时候,编译器就会这些目录下在查找头文件),这里应该输入是D:\MatLab6dot5\extern\include\cpp和D:\MatLab6dot5\extern\include。当然,我把MatLab6.5装到了D盘的MatLab6dot5目录下了。所以,从这里就可以看出,我们所需的头文件就存在这两个文件夹中,那么如果没有装MatLab的话,就拷贝这两个文件夹就行了(对.h/.hpp文件来说)。然后再选中“目录[S]”下接框中的"Library files"进行.lib文件库设置,其方法和“Include files”的设置道理是一样的,这里应该输入的文件夹是D:\MatLab6dot5\extern\lib\win32\microsoft\msvc60和D:\MatLab6dot5\extern\lib\win32。
  4、需要说明的是,第3步的设置是属于编译器的,也就是说,第3步的设置只需要设一次VC6.0就会铭记于心了。而在这一步要进行的设置是工程设置,这个设置是针对具体的工程的,所以,每一个要调用MatLab数学库的函数都要进行这一设置:“工程”—>“设置”把开“Project Settings”对话框,然后在对话框中的
   1)"c/c++"—>"分类"下拉框中选“预处理器”在“预处理器定义”文本框中增加MSVC,IBMPC,MSWIND这三个指令。
   2)"c/c++"—>"分类"下拉框中选“Code Generation”,在“Use run time library”下拉框中选中“Multithreaded DLL”。
   3)“连接”—>“对像/库模块”文件框中增加libmatpm.lib libmmfile.lib libmatlb.lib libmat.lib libmx.lib 这个静态库。

   。。。。所有的设置终于做完了,非常的辛苦,要不然怎么叫C++呢。。。。。。。。继续:
  5、在工程(刚才说了,这是一个DLL工程)中添加一个源文件,就叫s.cpp吧,在s.cpp中输入以下代码:
  #include "matlab.hpp"
  #include
  int LU(int n,double* A,double* B,double* X)
  {
   mwArray a(n,n,A);
   mwArray b(n,1,B);
   mwArray L;
   mwArray U;
   mwArray x;
   L=lu(&U,a);
   x=mldivide(U,mldivide(L,b));//用LU分解求方程组
   x.ExtractData(X);//得到mwArray中的数
   return 1;
  }
  说明一下这段代码:首先,#include "matlab.hpp"是必不可少的,要不然编设器真不知道我是调用MatLab中的函数。其次,在MatLab的世界里,所有的数(组)都是矩阵,哪怕只是做一个简单的1+1=2,其实都是矩阵们之间的交易。c++数学库函数的调用方式和MatLab里的调用方式非常相似,当然进行交易的也都是一些矩阵,这里的mwArray类(注意,这是一类),就是一个矩阵,在C库里面就是mxArray结构体,mwArray类其实是有一个指向一个mxArray结构体的指针,关于这个就不多说了。其实关于这个看是很简单的函数,如果细细的去读它,会发现一些小问题(这里的问题不是说这个函数有错),这些问题是须要弄明白的。
  6、要使这个dll知道它其有被“别人”调用的功能,就必须要声明哪些函数(当然这个例子中只有一个函数,但实际上,可能不只一个)是要导出的。关于这个有两种方式,我在这里采用的是一种通过性较好的方式——运用.def文件。所以,在这个工程中增加一个文体文件,并把它命名为“dll_1.def”,这里的.def护展名需要手动的键入。并在dll_1.def中输入以下的代码:
  LIBRARY dll_1
  EXPORTS
  LU @1
  说明一下,“LIBRARY”之后的“dll_1”是工程名,也是要生成的DLL的名字,这里的"EXPORTS"的中文意思好像是输出吧,呵呵。“LU”当然就是刚才在s.cpp文件中写的那个函数的名字了。
  7、编译工程,生成dll。“组建”—>“组建[dll_1.dll]”。于是,会发现在工程所在的文件目录下就的bin/Debug文件夹中就生成了一个dll_1.dll文件了,这就是我们想要的东西了。
  8、在C#中调用dll_1.dll中的函数(具体来说,是调用LU这个函数)。打开VS2008,新建一个C#窗口工程吧。啊,刚刚把vc6.0关掉,现在又打开VS2008,真是倍感亲切和畅快,因为在C#里面,好像一切都不那么拘束了,很随便。在C#里,没有单独的函数了,所有都是对像,函数就只能存在于对像之内了,像调入的C++DLL中的函数,一般都只能是对像的静态成员函数。于是,在工程中增加一个类,随便取个名字吧,叫cppDllInvokeDemo,具体的代码如下:
  using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Text;
  using System.Runtime.InteropServices; //注意加入这个命名空间
  namespace CshapWinInvokeCppDll
  {
   class cppDllInvokeDemo
   {
   const string dll_1 = "dll_1.dll";
   [DllImport(dll_1, CallingConvention = CallingConvention.Cdecl)]
   public static extern int LU(int n, double[] A,double[] B,double[] X);
   }
  }
  说明一下:using System.Runtime.InteropServices;这个命名空间是必须的。由于不想在C#里面用指针,所在这里的LU函数签名内指针变成了数组,这个转换是非常顺畅的。
  9、在C#的这个工程中调用这个LU函数.示例代码如下:
  private void button3_Click(object sender, EventArgs e)
   {
   double[] A = { 2, 1, 0, 1, 1, -5, 2, 6, -5, 0, 1, -1, 1, 7, -1, -4 };
   double[] B = { 13, -9, 6, 0 };
   double[] X=new double[4];
   cppDllInvokeDemo.LU(B.Length, A, B, X);
   textBox3.Text = X[0].ToString();
   }
  显然上面这个函数是一个事件处理函数,也很显然我的窗口中有一个button3按件和一个textBox3文框。
  Good luck!
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值