vs2010matlab混合编程
A. 如何vs2010mfc调用matlab 2010生成dll进行编程
通常在实现图像处理的算法时我们使用Matlab编程,因为它具有丰富的库函数以及操作方便,然而在工程项目中通常使用C/C++语言。如果我们将matlab代码完全重写成C++代码会很麻烦,最好的办法是借助matlab与C/C++接口将.m程序转成dll文件!
一、使用matlab将.m转成dll文件
1、在命令行中输入mex -setup
提示你是否要在本地安装matlab compilers,然后选择compiler类型,有matlab自带的编辑器以及检测到的其他编辑器,比如“Microsoft Visual C/C++ version 6.0 in E:\Program Files\Microsoft Visual Studio”,根据自己实际情况选择。
2、在命令行中输入mbuild -setup
这里的选项和上面类似,依次选择环境确定。
3、生成dll文件
一句命令mcc -W cpplib:add -T link:lib add.m
前面的add表示生成的dll文件名,后面的add.m顾名思义是.m文件名。生成后会多出8个文件,有用的是add.ctfadd.dll add.lib add.h4个文件,据说新版的Matlab不会生成.ctf文件。
二、VC6.0中调用生成的dll文件
上面生成的dll文件,我们可以借助VC6.0的Depends工具查看导出函数名,但是我们要调用导出函数必须要知道函数的形参返回类型等,这里要借助.h文件,它包含了导出函数的声明,下面以实例来讲解使用方法:
1、add.m文件
function [a,b]=add(x,y)
a=2*x+y;
b=3*y;
end
注意了add函数有两个返回值,可以猜测一下在C++中是如何处理的;
2、add.h文件
截取其中一段关键代码如下:
extern void add(int nargout, mwArray& a, mwArray& b
, const mwArray& x, const mwArray& y);
实际上函数的返回是变相的放到形参中的,依次是输出参数个数,输出参数,输入参数。PS 现在做的这个项目中用户自定义算法dll使用的规则和这里类似!
3、C++中调用dll文件
(1)新建空工程,将上面提及的4个文件放到工程目录下;
(2)VC++目录中包含目录:matlab 内的include目录
比如我的是 E:\MATLAB7\extern\include
(3)VC++目录中库目录:matlab 内的lib目录
E:\MATLAB7\extern\lib\win32\microsoft\msvc60,要根据VC++版本修改!
(4)工程属性-》连接-》输入-》附加依赖项
输入:add.lib mclmcrrt.lib mclmcr.lib,第一个是生成的。或者在预处理中加入下面代码
#pragma comment(lib, "mclmcrrt.lib")
#pragma comment(lib, "mclmcr.lib")
#pragma comment(lib, "add.lib")
4、C++代码
#include <iostream>
#include "add.h"
using namespace std;
int main()
{
if(!addInitialize())
{
cout<<"initilize failed!!!"<<endl;
return -1;
}
mwArray a(1,1,mxDOUBLE_CLASS);
mwArray b(1,1,mxDOUBLE_CLASS);
a(1,1)=20;
b(1,1)=30;
mwArray x(1,1,mxDOUBLE_CLASS);
mwArray y(1,1,mxDOUBLE_CLASS);
//输出参数个数,输出参数,输入参数。
add(2,x,y,a,b);
double *i=new double;
double *j=new double ;
x.GetData(i,1);
y.GetData(j,1);
cout<<"x="<<*i<<" y="<<*j<<endl;
getchar();
return 0;
}
注意:addInitialize()一定要!
B. 如何在MATLAB R2010a 中使用Visual C++ 2010编译器
1、安装补丁VS2010MEXSupport.zip
由于MATLAB R2010a 发布的时间要比 VS2010早,所以在该版本识别不了VC++2010编译器。不过R2010a之后的版本应该不会有这种问题了。
解压补丁包,将其中的文件放到 D:Program 文件夹下。
2、在MATLAB中安装VC++ 2010 编译器
打开Matlab,在 command window 中输入 mex -setup
>> mex -setup
Please choose your compiler for building external interface (MEX) files:
Would you like mex to locate installed compilers [y]/n?n (一定要选择 n)
Select a compiler:
[1] Intel C++ 11.1 (with Microsoft Visual C++ 2008 SP1 linker)
[2] Intel C++ 9.1 (with Microsoft Visual C++ 2005 SP1 linker)
[3] Intel Visual Fortran 11.1 (with Microsoft Visual C++ 2008 SP1 linker)
[4] Intel Visual Fortran 11.1 (with Microsoft Visual C++ 2008 Shell linker)
[5] Intel Visual Fortran 10.1 (with Microsoft Visual C++ 2005 SP1 linker)
[6] Lcc-win32 C 2.4.1
[7] Microsoft Visual C++ 6.0
[8] Microsoft Visual C++ 2005 SP1
[9] Microsoft Visual C++ 2008 Express
[10] Microsoft Visual C++ 2008 SP1
[11] Microsoft Visual C++ 2010
[12] Microsoft Visual C++ 2010 Express
[13] Open WATCOM C++
[0] None
Compiler:12
注意,如果选择 n 之后,没有列出这么多编译器选项,甚至没有出现VC++ 2010。 不要慌,此时选择 0,即None。
Compiler: 0
mex: No compiler selected. No action taken.
Warning: The MATLAB C and Fortran API has changed to support MATLAB
variables with more than 2^32-1 elements. In the near future
you will be required to update your code to utilize the new
API. You can find more information about this at:
http://www.mathworks.com/support/solutions/en/data/1-5C27B9/?solution=1-5C27B9
Building with the -largeArrayDims option enables the new API.
然后在command window 里再次输入 mex -setup。
>> mex -setup
Please choose your compiler for building external interface (MEX) files:
Would you like mex to locate installed compilers [y]/n?n (一定要选择 n)
此时就会列出很多编译器,包括已经VC++2010。如果还没有,可重复几次以上过程。当然前提是必须安装VS2010,否则,再怎么重复,也找不到VC++2010编译器。
列出VC++2010编译器之后,我相信接下该怎么做对大家来说没问题。
3、error C2371: 'char16_t' : redefinition; different basic types
在混合编程中,也许会出现如下错误:
C:Microsoft Visual Studio 10.0VCINCLUDEyvals.h(576) : error C2371: 'char16_t' : redefinition; different basic types
C:.h(330) : see declaration of 'char16_t'
原因是VS2010中的yvals.h添加了char16_t的定义,而Matlab的matrix.h也包含对char16_t的定义,所以同时包含这两个头文件的话,会导致重复定义char16_t的错误。
完全没有必要修改这两个头文件(以防修改之后,会在将来导致一些问题),只需要在包含matrix.h之前包含yvals.h即可。例如:
#include<yvals.h>
#if(_MSC_VER>=1600)
#define__STDC_UTF_16__
#endif
#include"mex.h"
mex.h 包含matrix.h。这就要求我们必须知道所包含的头文件是否包含matrix.h。
C. 怎么用matlab code封装matlab算法制作独立的动态链接库
一,设置操作系统的环境变量。
系统变量增加D:R2011abinwin32;D:R2011abin和E:Microsoft Visual Studio 10.0VCbin,这个分别是我的机器上matlab和VS安装目录下的路径。
系统变量设置完毕后需要重新启动计算机方能生效。
二,设置matlab的编译环境
在matlab中输入命令mex -setup,选择Microsoft Visual C++ 2010
再输入命令mbuild -setup 同样选择Microsoft Visual C++ 2010
p.s. 这一步中,在我自己配置的过程中,matlab可以很容易的识别出机器上装有的编译器以及他们的安装路径,其中包括VS2010,选择它就是了。也许有的环境下matlab不一定能找出VS2010中的VC编译器,这个怎么解决就不知道了。
三,matlab编译.m文件
输入mcc -W cpplib:yourfunLib -T link:lib yourfun.m
其中,yourfunLib是生成的DLL,Lib的前缀名字,也就是你最后可以是使用的DLL以及Lib库的名字;yourfun是你需要编译的.m函数。
编译完成后得到了下图中的一些文件:
这些文件中后缀为DLL,LIB,H的文件在VS调用的时候有用,其他文件目前没有使用。(这里我把yourfunLib指定为aetherLib了)
四,VS2010 的配置
新建一个控制台项目。
打开项目的属性页,针对这个项目做如下的设置:
1.VC++目录下的包含目录添加
D:R2011aexterninclude(matlab安装目录下的路径)
D:R2011aexternincludewin32(matlab安装目录下的路径,下同)
C:(你自己新建的项目中的路径,下同)
2.VC++目录下的库目录添加
D:R2011abinwin32
D:R2011aexternlib
C:
D:R2011aexternlibwin64microsoft
D:R2011aexternlibwin32lcc
D:R2011aexternlibwin32microsoft
3.c/c++中的常规里面的附加包含目录添加
D:R2011aexterninclude
4.连接器下面的常规中的附加库目录添加
D:R2011aexternlibwin32microsoft
5.连接器下面的输入中的附加依赖项添加
libeng.lib
libmat.lib
libmex.lib
libmx.lib
mclmcrrt.lib
mclmcr.lib
aetherLib.lib(这个是你自己用matlab生成的lib,前面的是matlab自身计算引擎中的lib)
在解决方案资源管理其中的头文件和资源文件中添加文件
1.在头文件中添加生成的.h文件
2.在资源文件中添加.lib,.dll文件
3.然后 把.h,.lib,.dll文件拷到你新建的项目的目录下。比如我把他们放到了C:里面。
编写代码调用dll中的函数
dll中的函数的接口形式在.h文件的最后面给出了,你可以去翻看他接口形式。这里面的函数的输入输出参数都得是mwArray对象的常引用,关于这个类请读者自己去网上搜索资料。你需要搞明白的是mwArray是matlab公司专门针对“c++调用matlab生成的dll“ 而设计的类,因为你包含了matlab安装目录下的这些类,所以你可以在VS里使用它们。
下面是一段主函数的编写样例:
// newdll.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include
#include "engine.h"
#include "mclmcr.h"
#include "mclcppclass.h"
#include "libMyAdd.h"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
if(!libMyAddInitialize())
{
//initilize failed!!!"<<std::endl;
std::cout<<"错误..."<<std::endl;
return -1;
}
double a = 6;
double b = 9;
double c;
mwArray mwA(1, 1, mxDOUBLE_CLASS);
mwArray mwB(1, 1, mxDOUBLE_CLASS);
mwArray mwC(1, 1, mxDOUBLE_CLASS);
mwA.SetData(&a, 1);
mwB.SetData(&b, 1);
MyAdd(1, mwC, mwA, mwB);
c = mwC.Get(1,1);
cout<<c<<endl;
system("PAUSE");
return 0;
}
这个dll中的函数只是实现了一个简单的两数相加的功能,是我做基本配置是使用的。
#include "engine.h"
#include "mclmcr.h"
#include "mclcppclass.h"
#include "libMyAdd.h"这些头文件是必须包含的,其中engine好像是包含了matlab计算引擎中的所有dll(还没有认真考证)
现在,运气好的话你应该能看到你预想中的输出了。如果出现了问题,比如找不到路径,不可访问等等各种错误,那只能你自己去解决了,我搞了整整3天,上面提到的错误都有遇到。出了错误你可以尝试去网络搜索其他博客,更好的是去google用英文搜索相关的问题,一些社区里面也许有答案呢,matlab版主文档我倒是没仔细看,也许上面也有不错的帮助呢! good luckto you!
备注:
1.我自己在搞的时候,遇到的问题是.m函数中本身就使用了c++语言编写的dll,然后再封装这个.m函数。这种情况下你得保证VS可以访问到你用到的那些用C++书写的dll。但是只要用mcc命令编译.m函数后,你在连接器下面的输入中的附加依赖项中只需添加.m 生成的dll函数就可以了,不需要添加那些c++代码生成的dll。这里建议你把matlab项目拷到VS项目中,直接在Vs项目中工作进行MCC编译。
2.主函数代码中if(!libMyAddInitialize())是必须的。
D. vs2010怎样读取.mat文件
mat数据格式是matlab的数据存储的标准格式。
可以在Matlab中象M文件一样打开,数据进入workspace
可以调用matlab的子程序库,用c或fortan调用mat格式的数据。
给你几个函数名
matopen 打开mat文件
matclose 关闭mat文件
magetfp 取得mat文件的c语言句柄
matGetArray 取得一个数组