MATLAB和VS2010的混合编程需要注意的问题
2015-03-20 17:49
417 查看
接上一篇文章吧,虽然上一篇距离现在几个月了。2015年第一发。
对于BM3D算法,在作者的主页他们给出了MATLAB的代码,在MATLAB上跑了一下,果然很好很强大,同时也跑了跑实验验证了一下linux下的C++版代码,需要装libpng和fftw3这两个库。后来在师兄的帮助下实现了GPU版的程序,可以做到每秒5-10帧左右,又大幅的提升了算法的速度,但是由于自己太懒,于是想到借用MATLAB来进行对图像的IO操作,在不同域之间做变换以及计算性能。 因而在去年底和今年初的一个月时间摸索了一下MATLAB和VS2010混合编程互相调用的方法,写下来以纪念一下走过的弯路。虽然网上其他的地方都已经有很多格式的有关于此的教程,但是我在搜索的过程中发现这些教程要么就不全要么就一笔带过,这篇文章打算从自己实际项目的角度出发,写一写遇到的问题以及使用的方法。
然后根据提示选择编译器,我用的VS2010,然后一直选择y,完成之后,再在命令行中输入:
然后根据提示选择编译器,我用的VS2010,然后一直选择y,完成之后,MATLAB端就配置好了
2. 再配置VS2010,新建一个工程,比如matlab_demo,在工程名右键单击,选择:属性(property) -->
1). VC++目录 -->
(1). 包含目录 (加入matlab的外部接口目录, 比如 我的是:D:\Program Files\MATLAB\R2011b\extern\include)
(2). 库目录 (加入matlab的库目录, 比如 我的是:D:\Program Files\MATLAB\R2011b\extern\lib\win64\microsoft,注意需要根据操作系统位数选择win64还是win32)
2). 链接器(linker) -->输入(input) --> 附加依赖项(Additional Dependencies)
添加三个依赖库:libmat.lib libeng.lib libmx.lib
(这三个库都在D:\Program Files\MATLAB\R2011b\bin\win64中)
3.在源代码中新建一个.cpp文件,加入代码(见下文)就可以调用了
到这里配置完毕
2. 以下是添加具有C风格的代码,
-添加变量:
①首先在c文件中new一个对象,可以任何数据类型
②在C中,能用于MATLAB操作的变量类型是mxArray 然后利用mxCreateDoubleMatrix()创建一个变量
三个参数分别是创建矩阵的行,列和类型,一般使用mxREAL类型
③最后利用memcpy函数将C/C++变量传递到MATLAB中:
经过以上三步就成功在cpp中建立了变量,接下来是把建立的变量传入到MATLAB中
-调用MATLAB
把c代码中的变量传到MATLAB中去:只能传mxArray格式
// c中变量叫var_in_matlab 与其对应的MATLAB变量名为variable
// engEvalString调用MATLAB引擎执行代码,引号内为满足MATLAB语法的代码
// 操作完毕之后,释放内存
// 关闭MATLAB引擎链接
附个完整版:
#include "matrix.h"
#include "libr2y.h"
#include "libtrans.h"
#include "mclmcr.h"
#include "mclcppclass.h"
#pragma comment( lib, "mclmcr.lib" )
#pragma comment( lib, "libmx.lib"
4000
)
#pragma comment( lib, "libmat.lib" )
#pragma comment( lib, "mclmcrrt.lib" )
#pragma comment( lib, "libtrans.lib")
#pragma comment( lib, "libr2y.lib")
#pragma comment( lib, "mclmcrrt.lib")
int main()
{
Engine *ep;// 定义一个调用matlab的对象
if (!(ep = engOpen(NULL))) // 测试MATLAB能否被调用
{
fprintf(stderr, "\nCan't start MATLAB engine\n");
return EXIT_FAILURE;
}
/* matlab矩阵生成函数API
*
* mxCreateDoubleMatrix(row, col, type), 申请函数matlab引擎中使用mxArray数据类型
* \param row 申请矩阵的行数
* \param col 申请矩阵的列数
* \param type 矩阵元素的数据类型,mxREAL为双精度
*
* 申请完毕之后,使用memcpy函数给申请的数组赋值
**/
mxArray *T = NULL, *result = NULL;
T = mxCreateDoubleMatrix(1, Nsample, mxREAL);
memcpy( (void *)mxGetPr(T), (void *)t, Nsample*sizeof(t[0]) ); // 将t中的数据复制到T中
double *V = new double;*V = 20;
mxArray *v = NULL;
v = mxCreateDoubleMatrix(1, 1, mxREAL);
memcpy((void *)mxGetPr(v), (void *)V, sizeof(double));
engEvalString(ep,"path(path,'E:\\Nonlocal Solver Package')"); // 注意双斜杠
engPutVariable(ep, "v", v);
engEvalString(ep, "[PSNR, ImgRec] = NLS1(v)");
fgetc(stdin);
mxDestroyArray(v);
delete V;
engEvalString(ep, "close;");
engClose(ep);
return EXIT_SUCCESS;
}
3. 以下是添加具有C++风格的代码
1). 在matlab的命令行中输入以下命令
mcc -W cpplib:libname -T link:lib filename.m
即可在matlab中编译生成filename文件对应的C++库。输入的命令中libname是生成的一系列C++库的文件名(包括.cpp .h .dll .lib .exp .exports 以及两个描述生成过程的文本文档),而filename.m则是需要生成C++库的matlab文件。
以上是生成的cpp的库, 如果是想要纯c的库就输入:
2). 生成了图中所示的文件之后。
-需要在VS工程用到的只有其中的三个(.h .lib 和 .dll)文件,将这三个文件拷到VS工程的目录下,然后在所建立的VS工程名处点击右键->添加->现有项->选中这三个文件->确 定
-并在VS的cpp代码最开始加上
和
# 系统环境变量path中添加:D:\Program Files\MATLAB\R2011b\bin\win64 ( 即:你的MATLAB安装文件地址下的这个目录 )
2. 在#include "engine.h"中报错的情况
# 没有配置好 重新配置
3. engOpen函数始终无法打开的情况
# MATLAB组件没有在注册表中注册。
# 注册方法:开始-->运行-->cmd
在命令行中把当前路径从C:\windows\system32修改到MATLAB的安装路径的bin下:
比如我的是D:\Program Files\MATLAB\R2011b\bin, 然后在命令行中输入:
进行注册
如果注册成功,会弹出MATLAB的命令行窗口
4. 在VS 2010中调用matlab生成的C++风格的代码进行编程的时候,需要在main函数的最开始的地方执行以下代码:
PS:这个问题困扰了我很久,一直没找到解决的办法,后来在国外的一个网站的角落看到的。。。
5. 在.h文件中可以看到我们需要调用的函数的api,打开.h文件只需要看两个地方
- 直接拉到文件末尾,这是我们需要使用的函数:
void类型的rgb2yuv()函数,这个函数有2个参数,他们分别的含义是:
- 另一个地方是
这两个函数分别对应了在VS中调用rgb2yuv()函数的初始化命令和结束命令。也就是说必须在这两个函数位置的中间调用rgb2yuv()才行,即在.cpp代码中应该按照下面的方式来写:
6. 数据的初始化和使用:
mwArray是MATLAB和VS交互变成中专门定义的数据对象,所有MATLAB生成的C++库函数的参数类型都是对它的引用,也就是所有的matlab矩阵类型都可以用它表示,使用方法如下:
// 用C++内存中的变量给matlab程序中的变量赋值
// 首先定义一个C++变量
// 再定义一个matlab对象
// 用默认构造函数初始化,三个参数分别是:SIGMA矩阵的行,列,每个元素的数据类型
// 对matlab的对象进行赋值
// sigma是一个数组, 后面的1代表的是从数组起始位置开始数一共赋值几个值
// 加入 2.中的代码
对于BM3D算法,在作者的主页他们给出了MATLAB的代码,在MATLAB上跑了一下,果然很好很强大,同时也跑了跑实验验证了一下linux下的C++版代码,需要装libpng和fftw3这两个库。后来在师兄的帮助下实现了GPU版的程序,可以做到每秒5-10帧左右,又大幅的提升了算法的速度,但是由于自己太懒,于是想到借用MATLAB来进行对图像的IO操作,在不同域之间做变换以及计算性能。 因而在去年底和今年初的一个月时间摸索了一下MATLAB和VS2010混合编程互相调用的方法,写下来以纪念一下走过的弯路。虽然网上其他的地方都已经有很多格式的有关于此的教程,但是我在搜索的过程中发现这些教程要么就不全要么就一笔带过,这篇文章打算从自己实际项目的角度出发,写一写遇到的问题以及使用的方法。
一、在VS2010中调用MATLAB的方法:
1. 先是配置MATLAB,打开MATLAB 我用的是R2011b,在命令行中输入:mex -setup
然后根据提示选择编译器,我用的VS2010,然后一直选择y,完成之后,再在命令行中输入:
mbuild -setup
然后根据提示选择编译器,我用的VS2010,然后一直选择y,完成之后,MATLAB端就配置好了
2. 再配置VS2010,新建一个工程,比如matlab_demo,在工程名右键单击,选择:属性(property) -->
1). VC++目录 -->
(1). 包含目录 (加入matlab的外部接口目录, 比如 我的是:D:\Program Files\MATLAB\R2011b\extern\include)
(2). 库目录 (加入matlab的库目录, 比如 我的是:D:\Program Files\MATLAB\R2011b\extern\lib\win64\microsoft,注意需要根据操作系统位数选择win64还是win32)
2). 链接器(linker) -->输入(input) --> 附加依赖项(Additional Dependencies)
添加三个依赖库:libmat.lib libeng.lib libmx.lib
(这三个库都在D:\Program Files\MATLAB\R2011b\bin\win64中)
3.在源代码中新建一个.cpp文件,加入代码(见下文)就可以调用了
到这里配置完毕
二、在VS2010中调用MATLAB的代码:
1. 第一步是添加MATLAB在VS中的头文件以及lib库:#include "matrix.h" #include "libr2y.h" #include "libtrans.h" #include "mclmcr.h" #include "mclcppclass.h" #pragma comment( lib, "mclmcr.lib" ) #pragma comment( lib, "libmx.lib" ) #pragma comment( lib, "libmat.lib" ) #pragma comment( lib, "mclmcrrt.lib" ) #pragma comment( lib, "libtrans.lib") #pragma comment( lib, "libr2y.lib") #pragma comment( lib, "mclmcrrt.lib")
2. 以下是添加具有C风格的代码,
-添加变量:
①首先在c文件中new一个对象,可以任何数据类型
int* var = (int *)malloc(sizeof(int));
②在C中,能用于MATLAB操作的变量类型是mxArray 然后利用mxCreateDoubleMatrix()创建一个变量
mxArray *var_in_matlab = NULL; var_in_matlab = mxCreateDoubleMatrix(row, col, type);
三个参数分别是创建矩阵的行,列和类型,一般使用mxREAL类型
③最后利用memcpy函数将C/C++变量传递到MATLAB中:
memcpy( (void*)mxGetPr(var_in_matlab), (void *)var, sizeof(int) );
经过以上三步就成功在cpp中建立了变量,接下来是把建立的变量传入到MATLAB中
-调用MATLAB
把c代码中的变量传到MATLAB中去:只能传mxArray格式
Engine *ep; if ( !(ep = engOPen(NULL)) ) return -1;
// c中变量叫var_in_matlab 与其对应的MATLAB变量名为variable
engPutVariable(ep, "variable", var_in_matlab);
// engEvalString调用MATLAB引擎执行代码,引号内为满足MATLAB语法的代码
engEvalString(ep, "plot(variable)");
// 操作完毕之后,释放内存
mxDestroyArray(var_in_matlab); free(var);
// 关闭MATLAB引擎链接
engClose(ep);
附个完整版:
</pre><pre>
#include "matrix.h"
#include "libr2y.h"
#include "libtrans.h"
#include "mclmcr.h"
#include "mclcppclass.h"
#pragma comment( lib, "mclmcr.lib" )
#pragma comment( lib, "libmx.lib"
4000
)
#pragma comment( lib, "libmat.lib" )
#pragma comment( lib, "mclmcrrt.lib" )
#pragma comment( lib, "libtrans.lib")
#pragma comment( lib, "libr2y.lib")
#pragma comment( lib, "mclmcrrt.lib")
int main()
{
Engine *ep;// 定义一个调用matlab的对象
if (!(ep = engOpen(NULL))) // 测试MATLAB能否被调用
{
fprintf(stderr, "\nCan't start MATLAB engine\n");
return EXIT_FAILURE;
}
/* matlab矩阵生成函数API
*
* mxCreateDoubleMatrix(row, col, type), 申请函数matlab引擎中使用mxArray数据类型
* \param row 申请矩阵的行数
* \param col 申请矩阵的列数
* \param type 矩阵元素的数据类型,mxREAL为双精度
*
* 申请完毕之后,使用memcpy函数给申请的数组赋值
**/
mxArray *T = NULL, *result = NULL;
T = mxCreateDoubleMatrix(1, Nsample, mxREAL);
memcpy( (void *)mxGetPr(T), (void *)t, Nsample*sizeof(t[0]) ); // 将t中的数据复制到T中
double *V = new double;*V = 20;
mxArray *v = NULL;
v = mxCreateDoubleMatrix(1, 1, mxREAL);
memcpy((void *)mxGetPr(v), (void *)V, sizeof(double));
engEvalString(ep,"path(path,'E:\\Nonlocal Solver Package')"); // 注意双斜杠
engPutVariable(ep, "v", v);
engEvalString(ep, "[PSNR, ImgRec] = NLS1(v)");
fgetc(stdin);
mxDestroyArray(v);
delete V;
engEvalString(ep, "close;");
engClose(ep);
return EXIT_SUCCESS;
}
1). 在matlab的命令行中输入以下命令
mcc -W cpplib:libname -T link:lib filename.m
以上是生成的cpp的库, 如果是想要纯c的库就输入:
mcc c -W lib:libname -T link:lib filename.mfilename是对应的matlab源文件名。内容如下:
然后就会生成如下图的一些文件:
2). 生成了图中所示的文件之后。
-需要在VS工程用到的只有其中的三个(.h .lib 和 .dll)文件,将这三个文件拷到VS工程的目录下,然后在所建立的VS工程名处点击右键->添加->现有项->选中这三个文件->确 定
-并在VS的cpp代码最开始加上
#include "libr2y.h"
和
#pragma comment( lib, "libr2y.lib" )//这里没有分号3). 接下来就可以在VS中调用生成的函数了
三、在VS2010中调用MATLAB可能遇到的问题:
1. 在运行时丢失libeng.dll的情况# 系统环境变量path中添加:D:\Program Files\MATLAB\R2011b\bin\win64 ( 即:你的MATLAB安装文件地址下的这个目录 )
2. 在#include "engine.h"中报错的情况
# 没有配置好 重新配置
3. engOpen函数始终无法打开的情况
# MATLAB组件没有在注册表中注册。
# 注册方法:开始-->运行-->cmd
在命令行中把当前路径从C:\windows\system32修改到MATLAB的安装路径的bin下:
比如我的是D:\Program Files\MATLAB\R2011b\bin, 然后在命令行中输入:
matlab/regserver
进行注册
如果注册成功,会弹出MATLAB的命令行窗口
4. 在VS 2010中调用matlab生成的C++风格的代码进行编程的时候,需要在main函数的最开始的地方执行以下代码:
if ( !mclInitializeApplication(NULL,0) ) { printf("MCL Inittialized Failed!\n"); exit(EXIT_FAILURE); }# 否则会报出异常,内存违规访问。因为这个话是用来检查是否已经对Mcl进行初始化,否则会出现内存异常,具体是Unhandled Exception C0X00...这是因为引用了未初始化的内存造成了异常。
PS:这个问题困扰了我很久,一直没找到解决的办法,后来在国外的一个网站的角落看到的。。。
5. 在.h文件中可以看到我们需要调用的函数的api,打开.h文件只需要看两个地方
- 直接拉到文件末尾,这是我们需要使用的函数:
void类型的rgb2yuv()函数,这个函数有2个参数,他们分别的含义是:
const mwArray& src; // 对应matlab程序中rgb2yuv.m中的src参数 const mwArray& sigma; // 对应matlab程序rgb2yuv.m中的sigma参数
- 另一个地方是
这两个函数分别对应了在VS中调用rgb2yuv()函数的初始化命令和结束命令。也就是说必须在这两个函数位置的中间调用rgb2yuv()才行,即在.cpp代码中应该按照下面的方式来写:
if ( !liby2vInitialize() ) { rgb2yuv(src, SIGMA); lib2yuvTerminate(); }
6. 数据的初始化和使用:
mwArray是MATLAB和VS交互变成中专门定义的数据对象,所有MATLAB生成的C++库函数的参数类型都是对它的引用,也就是所有的matlab矩阵类型都可以用它表示,使用方法如下:
// 用C++内存中的变量给matlab程序中的变量赋值
// 首先定义一个C++变量
int sigma[] = { 20 }; int chosen[] = { 1 };
// 再定义一个matlab对象
// 用默认构造函数初始化,三个参数分别是:SIGMA矩阵的行,列,每个元素的数据类型
mwArray SIGMA(1, 1, mxDOUBLE_CLASS); mwArray src(1, 1, mxUINT8_CLASS);
// 对matlab的对象进行赋值
// sigma是一个数组, 后面的1代表的是从数组起始位置开始数一共赋值几个值
SIGMA.SetData(sigma, 1); src.SetData(chosen ,1);
// 加入 2.中的代码
if ( !liby2vInitialize() ) { rgb2yuv(src, SIGMA); lib2yuvTerminate(); }
相关文章推荐
- VC和MATLAB混合开发需要注意的一个问题
- VC和MATLAB混合开发需要注意的一个问题
- matlab 引擎实现混合编程问题。
- Matlab 与 VC++ 混合编程过程详解(含问题部分解答)
- 选择TTL和CMOS混合电路时需要注意的一些问题
- 编程需要注意的一些问题
- matlab读取edit时需要注意的问题
- TLD算法-Matlab混合编程之配置问题
- C/C++ 32位机器和64位机器 差异问题总结 跨平台 移植问题 语言编程需要注意的64位和32机器的区别
- 【读书笔记】并发编程需要注意的几个典型问题
- SOCKET编程需要注意的问题
- ABAP编程需要注意的小问题
- 使用模板防止双倍混合需要注意的问题
- socket编程需要注意的问题
- tsql编程中需要注意的问题
- VS2010使用Visual.Assist.X破解补丁需要注意的问题
- 使用blueZ进行蓝牙编程时需要注意的问题
- 并发编程基础入门需要注意的问题
- 多线程+Webservice分布式编程时需要注意的COM问题
- 【读书笔记】并发编程需要注意的几个典型问题