VS通过调用matlab引擎方式在VS里调用matlab函数和自己写的.m文件
首先说vs和matlab混合编程网上有三种方法,分别是:
1.matlab编译成.dll给VS调用
这个可以脱离matlab,只需要把相关的文件拷入VS工程目录下,具体流程在下面粘贴几个链接,感觉写的挺好的。
1.matlab函数编译成库供C++调用(非常详细)
2.C/C++程序通过动态链接库调用MATLAB程序
但是好像不是所有的matlab程序都适用于这种方式,啊好烦啊 (≧﹏ ≦),最最最坑的是,在matlab里涉及到符号变量 syms ,编译完的.dl文件在vs里跑会提示无法识别的符号或函数,然后指向matlab文件用 syms 定义符号变量的那一行(这倒是很智能),现在也没有找到解决办法,网上有说是:编译成 .dll不能用 syms sym 这些,还有什么替换啥的,感觉太麻烦没有试,试下面那个脱离不了matlab的有点笨笨的方法吧, ( ̄_ ̄|||)
2. VS通过调用matlab引擎的方式
参考了下面几个链接,在这里留下:
1.在VS2008中调用Matlab的m文件(百度文库)
2.和上面一样(CSDN)
就是说,引擎的方式提供的matlab功能是最全面的,比如说上面那个"臭syms",用引擎的方式后来可以用。通过引擎的方式实际上是在程序中打开一个matlab进程,让matlab软件自己去运行自己的.m文件里的程序,这个当matlab文件需要修改的时候也比.dll方便,直接修改.m文件就行。在控制台还能看到matlab图标,是将matlab通过ActiveX 控件方式启动的。
环境 :: 这个值得一说,就是VS和matlab的版本和位数,我用了两个分别是
【VS2013(x64编译)+MATLAB2014a(64位)】 【VS2013(win32编译)+MATLAB2015b(32位)】
版本的话个人感觉MATLAB比VS高应该就差不多,或者matlab官网查一下支持。
VS2013一直是那个2013,好像它是32位的,然后在编译的时候可以选择编译活动平台是win32 还是x64,然后分别对应32位和64位的matlab,所以就是因为本来我的VS程序有些dll库是32位编译的,所以它编译的时候只能选择win32编译,不能选择x64,而想调用64位的matlab引擎编译方式必须选择x64编译,所以电脑上本来安装的64位版本matlab2014a不行,当时是新建一个控制台应用程序选择x64编译试了下可以调用引擎,然后再安装了32位的matlab(MATLAB2015是最后一个支持32位的matlab版本了)
下面说说流程:(用后一个环境吧,可以边做边记录,前一个已经好了)
-
安装了VS2013和matlab2015b(32位)(超级推荐软件安装管家公众号,这个神仙公众号!!!)
-
配置编译器(包含引擎头文件engine.h并引入Matlab对应的库文件libmx.lib、libmat.lib、libeng.lib)
- VS里新建一个控制台应用程序
- 右键项目-属性-VC++目录-包含目录 :D:\MATLAB2015\R2015b\extern\include
- 右键项目-属性-VC++目录-库目录 :D:\MATLAB2015\R2015b\extern\lib\win32\microsoft
- 右键项目-属性-连接器-输入:在附加依赖项编辑框中,添加文件名libmx.lib libmat.lib libeng.lib
#include "enging.h"
该文件包含了引擎API函数的说明和所需数据结构的定义。- 测试程序:
2.1调用matlab自带函数
#include "stdafx.h"
#include <iostream>
#include "math.h"
#include "engine.h"
#pragma comment(lib,"libmx.lib")
#pragma comment(lib,"libmat.lib")
#pragma comment(lib,"libeng.lib")
int _tmain(int argc, _TCHAR* argv[])
{
const int N = 50;
double x[N], y[N];
int j = 1;
for ( int i = 0; i < N; i++)
{
x[i] = i + 1;
y[i] = sin(x[i] + j*log(x[i]));
j *= -1;
}
Engine *ep; //定义matlab引擎指针
if (!(ep = engOpen(NULL))) //打开引擎 测试是否启动引擎成功
{
std::cout << "Can't start Matlab enfine!" << std::endl;
//exit(1);
}
//定义mxArray类型的1行N列的实数数组
mxArray *xx = mxCreateDoubleMatrix(1, N, mxREAL);
mxArray *yy = mxCreateDoubleMatrix(1, N, mxREAL);
//将数组x复制到mxArray数组xx中,将数组y复制到mxArray数组yy中
memcpy(mxGetPr(xx), x, N*sizeof(double));
memcpy(mxGetPr(yy), y, N*sizeof(double));
//将mxArray数组xx写入matlab工作空间,命名为xx
//将mxArray数组yy写入matlab工作空间,命名为yy
engPutVariable(ep, "xx", xx);
engPutVariable(ep, "yy", yy);
//engEvalString(ep, "plot(xx,yy);"); //像matlab发送画图命令
//engEvalString(ep, "benchmarkRRT()");
engEvalString(ep, "Control1()");
mxDestroyArray(xx);
mxDestroyArray(yy);
std::cout << "press any key to exit" << std::endl;
std::cin.get();
engClose(ep); //关闭引擎
return 0;
}
2.2 碰到的问题
虽然上面的步骤完成了,但是在程序运行的时候会碰到一些问题,
-
引擎打开不成功,每次运行一闪而过,加断点发现每次都是引擎打不开直接退出了,这个是在 第一个环境下(VS2013(win32编译)+MATLAB2014a(64位) 出现的问题(解决了,没留下图…),可能是我那个matlab重装系统之后没有注册,按网上的方法VS与MATLAB混合编程出现打不开引擎的问题把matlab注册一下就好了。
方法:先用管理员身份打开cmd,输入指令 cd/d D:\MATLAB\R2014a\bin 到matlab文件夹下面,再输入指令 matlab /regserver (这里千万注意指令中间有个空格空格空格,额,,,没有输入空格只是运行出了matlab而已)会弹出那个框。然后在程序里就能运行过打开引擎那一步了。
-
如果安装了两个matlab软件,调用引擎的时候,默认打开的是最新注册的版本的matlab软件,这个为啥,还不知道。。。
-
提示缺失一些.dll文件,这些文件是在 D:\MATLAB2015\R2015b\bin\win32 文件夹下面的,当然可以挨个找到然后都复制到工程的 Debug 文件下,但是不止图片上的一个哦,需要超级超级多的 .dll,一个一个找或者把那里的全部.dll都粘贴过来也太尴尬了吧,强迫症会受不了的,别想了,没门没门~
需要理解一下项目寻找dll文件的流程,主要就是会在当前文件夹下搜,然后在系统的环境变量文件里搜,所以需要把那个文件夹路径添加到系统的环境变量里面,这样得劲儿多了(Debug里不会那么乱)~~,值得注意的是:改完直接运行还是会提醒找不到,关闭解决方案再打开还是一样,把VS软件关了,再打开就好了,不容易额。
也就是这个链接说的这样 : VS2008调用matlab引擎找不到dll问题
然后对于利用引擎调用matlab自带函数实现matlab函数功能就实现了,就是下图,那么怎么实现自己写的函数呢?
2.3 调自己写的matlab函数
下面是对于自己用matlab写的函数。我自己瞎想的烂七八糟的,能用,就是太 LOW 了,目前先这么凑活着吧。
观察一下,matlab里的polt函数有个.m文件,是在 D:\MATLAB2015\R2015b\toolbox文件夹里面,所以呢步骤:
- 在上述路径toolbox文件夹里里添加自己写的函数的m文件(mycontrol文件夹)
- matlab软件主页>设置路径>添加文件夹>写有自己matlab函数的文件夹,保存后重启matlab
//engEvalString(ep, "plot(xx,yy);"); //像matlab发送画图命令
engEvalString(ep, "benchmarkRRT()");
engEvalString(ep, "Control1()");
下面一个链接备用:
- 例0:小试牛刀,在C++中调用MATLAB绘图
- 例1:使用engPutVariable函数向MATLAB引擎发送数据
- 例2:使用engGetVariable函数从MATLAB引擎中获取数据:
- 例3:向MATLAB引擎传入数据,然后从MATLAB引擎中获取3数据的计算结果: