C++调用matlab编程

C++调用Matlab,实在是不得已的方法。原文链接:

http://kylen314.blog.com/2012/12/11/matlab_for_cplusplus/  这是个很善良的博客,只出现了一个小小的错误!


内容:有少量修改!

噩耗啊噩耗啊!!!!最近本身就忙到吐,什么老板的专题研究,什么人脸性别识别,什么电功率分解算法研究,本身就快虚脱,然后昨天突然说一年半前申请的专利有个公式有点问题,我研究了半天也不知道一年半前的我为什么会写出那样的公式【囧】,然后昨天突然师兄跟我说,老板让我这周内搭出某个系统的演示平台,我勒个去,那个系统因为要从数字通信分析仪上获取数据,所以用NI公司的GPIB采集卡,驱动文件里面提供了C++的接口,然后之后数据我是用matlab处理的,必须妥妥的嘛,结果现在要搭个系统意味着采集和处理要继承在一起,我就怂了,我matlab里面调用了那么多计算方法不明的函数,要怎么移植到C++上啊,其实主要问题还是时间不够,时间充足什么都好说。。。

所以只好飞快研究C++怎么调用matlab的函数了。。。研究了一下,方法好像很多,比如使用MATLAB Engine,它可以在C++里面调用直接使用matlab的函数,但是对于我这个系统,最好可以直接调用整个matlab的function,虽然MATLAB Engine我不知道可不可以,没深究,后来研究了另外一个方法。总结一下当备忘。。


系统配置:

环境变量path中要加入matlab的bin目录:即加上X:/XXXXXX/MATLAB/R2009a/bin/win32

虽然,我发现好像装完matlab就已经自动加上了。。。

C++编译器配置:

不管用VS也好,还是VC6.0也好,VC6中是打开Tool→Options→Directories,VS中是打开Tool→Options→Project and Solution→VC++ Directories,然后添加以下东西:

  1. Include Files里面添加X:/XXXXXX/MATLAB/R2009a/extern/include
  2. Include Files里面添加X:/XXXXXX/MATLAB/R2009a/extern/include/win32
  3. Library Files里面添加X:/XXXXXX/MATLAB/R2009a/extern/lib/win32/microsoft

这样C++端就完成配置了。

Matlab的配置:

  1. 命令行中输入mbuild -setup,第一个选y,第二个选你的编译器,VS或者VC6.0对应的号码,一般是2,第三个再选y
  2. 命令行中输入mex -setup,选项和第一步一样。
配置完上面的东西,就可以了~

C++调用matlab使用方法:

  1. 首先写一个正确的matlab的m文件并保存,【额,不正确的我没试过。。】比如说是functin [a b] = function_name(c,d)
  2. matlab命令行中输入deploytool
  3. 在Deployment Tool左上角点击Create a new deployment project
  4. 选择Matlab Compiler中的C++ Share Library
  5. 并在下面输入你的Project名字和路径
  6. 右键Add files加入你之前写的m文件
  7. 点击Build the Project即可完成编译。
  8. 在你选择的Project的路径下有两个文件夹,distrib和src,src那个不用管,打开distrib
  9. 里面有三个文件是你要用的,.dll和.lib和.h文件
  10. 建立你的C++工程,并将上一步中的三个文件加入到你的C++工程中即可。

C++代码编写:

文件一开始要添加lib文件,代码如下:

#pragma comment(lib,"libdflapack.lib")  #这个文件在2010a里面找不到,要去掉
#pragma comment(lib,"libemlrt.lib")
#pragma comment(lib,"libeng.lib")
#pragma comment(lib,"libfixedpoint.lib")
#pragma comment(lib,"libmat.lib")
#pragma comment(lib,"libmex.lib")
#pragma comment(lib,"libmwlapack.lib")
#pragma comment(lib,"libmwservices.lib")
#pragma comment(lib,"libmx.lib")
#pragma comment(lib,"libut.lib")
#pragma comment(lib,"mclcommain.lib")
#pragma comment(lib,"mclmcr.lib")
#pragma comment(lib,"mclmcrrt.lib")

注意一下倒数第三个,据说matlab后面的版本是mclcommain.lib,之前的版本是mclco.lib,没考证,出了问题你去之前添加的lib路径下看一下就知道了。

然后添加你自己刚刚生成的lib文件

#pragma comment(lib,"XXX.lib")

之后必然要包含你自己的头文件啦。。

#include "XXX.h"

至于怎么用那些函数,简单说明一下,首先声明一下,下文中提到的XXX都是你在上面第五步中写的工程名,也就是上面lib和.h的XXX一样。

调用之前要先初始化,即调用函数:

XXXInitialize();

经过试验,上面那个函数的运行之间极其之长。。。

当然,在结束调用,或者在程序的尾部要调用:

XXXTerminate();

调用函数呢,就是你m文件的函数名,对了,众所周知m文件的文件名要和m文件里面的函数名一样,但是m文件的函数名不一定要和这里设置的Project一样,比如说函数名叫myfunction(),而工程名叫test,那么你生成的就是test.h,test.dll,test.lib,但是你在C++代码里面调用的时候用的却是myfunction。

如果你的myfunction没有输入输出参数,那么调用的时候就直接写myfunction()就可以了,如果有输入输出参数,函数调用格式是:

myfunction(int nargout, mwArray& matrix...,const mwArray& n1....);

直接理解就是输出参数个数nargout

然后nargout个输出参数,数据类型是mwArray,稍有常识的人只要看到函数调用里面有&就基本是输出参数啦~

然后就是各个输入参数,数据类型也是mwArray,看到const就知道应该是输入参数啦~

啥?你问我为什么不用写输入参数个数,好好复习matlab函数去!!!

关于mwArray:

这个是matlab生成的dll的接口数据类型,这个看上面的函数调用你就应该清楚这一点了,定义在matlab安装目录下的extern/include/下的mclcppclass.h下,有兴趣的自己看去~

虽然还有一种数据类型是mxArray,但是不推荐使用,而且mwArray本身就是对mxArray的封装!不推荐使用是因为它的内存管理方式不好,而且使用的时候要用指针,而mwArray你可以直接作为对象来操作。【如果要生成接口为mxArray的dll的话,也可以在matlab命令行里面使用申明,但都说了。。不推荐。。】

matlab里面不特别说明数据类型都是double,但是在这里定义一个mwArray数据的时候要说明类型,定义方法如下:

mwArray matrix(2,2,mxDOUBLE_CLASS);
mwArray matri2(1,m,mxINT8_CLASS);

如果要赋值或者读取,方法如下:

mwArray matrix(1,4,mxDOUBLE_CLASS);
double a[] = {1,2,3,4};
matrix.SetData(a,4);

cout<<matrix(1,2)<<endl;

double *b = new double[4];
matrix.GetData(b,4);
cout<<b[0];

可能出现的问题:

C++调用matlab生成的lib的时候可能会出现runtime error R6034的错误,虽然你可以关掉这个错误,程序可以继续跑,完全不碍事儿~但是也很烦,官方给出的说法是这样子的:

Summary

On Windows (XP or Vista) error R6034 is thrown by C runtime.

Description

On Windows (XP or Vista) error R6034 is thrown by the C runtime. This happens when executing standalone applications, C or C++ user applications built using C or C++ shared libraries, MATLAB Builder JA components, and MATAB Builder NE components.

In this case, the user has a PATH directory containing msvcr80.dll. The error is thrown because the version of tbbmalloc.dll in mcrinstallroot|matlabroot\bin\arch does not contain a manifest.

Workaround

For standalone executables and C/C++ shared libraries using a supported Microsoft Visual Compiler:

  1. Download the zip files in the attachment. New option files have been provided for both 32-bit and 64-bit Windows. These new options files create executables with manifests which the operating system uses to locate runtime shared libraries in the Windows side X side area. Applications created using the attached options files can be distributed to deployed machines without any change to the target MCR install area.
  2. Back up matlabroot\bin\arch\mbuildopts by executing the following at the system command prompt: cd matlabroot\bin\arch & mkdir mbuildopts.bak & cd mbuildopts & copy *.*..\mbuildopts.bak where matlabroot is the MATLAB installation directory which can be found by typing: matlabroot at the MATLAB command prompt and arch is the platform.
  3. Unzip either options_win32.zip or options_win64.zip to the root of your MATLAB installation directory.
  4. Execute mbuild -setup.
  5. Rebuild your application using the downloaded options files which you enabled by executingmbuild -setup.

For standalone executables and C/C++ shared libraries Using Lcc-win32 compiler:

  1. Create a manifest file named application_name.exe.manifest (if creating an executable) orapplication_name.dll.manifest (if creating a shared library) with the following content:
    <?xml version='1.0' encoding='UTF-8' standalone='yes'?> 
    <assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'> 
    <dependency> 
    <dependentAssembly> 
    <assemblyIdentity type='win32' name='Microsoft.VC80.CRT' version='8.0.50727.762' processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b' /> 
    </dependentAssembly> 
    </dependency> 
    </assembly>

    You can create this manifest file by copying the above content into a text file.

  2. Place the manifest in the same folder as the executable. For example, if you have an application called matrixdriver.exe, you would create a manifest file calledmatrixdriver.exe.manifest and put it in the same folder as the application.

For MATLAB Builder for JA and MATLAB Builder for NE, perform the following on your development machine:

  1. Change your folder to matlabroot\bin\arch
  2. Backup tbbmalloc.dll and rename it to tbbmalloc.dll.bak
  3. Execute the following command at a Visual Studio Command Prompt: mt.exe -inputresource:libut.dll;#2 -outputresource:tbbmalloc.dll;#2
  4. tbbmalloc.dll now contains a manifest, and must be distributed to any machine on which you have encountered error R6034 when executing a MATLAB Builder JA or MATLAB Builder NE component. You should place the modified tbbmalloc.dll in mcrroot\bin\arch where mcrroot is the MATLAB Compiler Runtime (MCR) installation directory.

Fix

For R2009b, a new version of tbbmalloc.dll is distributed that contains a manifest.

Attachments

但是这个问题也不一定会发生,我在我电脑上跑的时候出现了这个问题,但是在另一台新装matlab的电脑上就没出现,也许和网上传言的一样,重装一下就可以了。。不过好麻烦的说。。。


posted @ 2014-06-25 10:03  wishchin  阅读(1048)  评论(0编辑  收藏  举报