0.准备工作
<1>编译环境:MATLAB2016(X64)+VS2015+win10
<2>目的:数据可视化
<3>参考资料:https://www.cnblogs.com/Vonng/p/4232586.html
http://blog.sina.com.cn/s/blog_67d069a90100q37c.html
https://www.cnblogs.com/xpvincent/archive/2013/02/05/2893046.html
http://blog.sina.com.cn/s/blog_7e2e98ad0101hef2.html
https://blog.csdn.net/u010177286/article/details/45276315
1.Matlab的编译介绍(了解,不是步骤中的一步)
MATLAB编译器将M文件作为输入,产生可以独立运行的应用程序或相应的组件软件。产生的应用程序及组件软件,都是与平台相关的。MATLAB编译器可以产生以下几种应用程序或软件组件:用程序或相应的组件软件。产生的应用程序及组件软件,都是与平台相关的。MATLAB编译器可以产生以下几种应用程序或软件组件:c或C++共享库:在Windows系统中为动态链接库DLL,这些库也可以在没有MATLAB的用户机器上运行。
在MATLAB中,采用mbuild命令进行编译器的配置。mbuild命令的详细使用情况,用户可以在MATLAB的命令行窗口输入: help mbuild进行查看。通常情况下,mbuild命令中的setup选项就可以进行第三方编译器的设置。利用MATLAB编译器可以将M文件编译为可执行文件(在Window下为.exe文件),或者动态链接库。下面详细的介绍如何利用命令mbuild进行MATLAB编译器的安装和配置。
MATLAB编译器采用MATLAB Component Runtime (MCR)技术,完全支持MATLAB语言。在利用MATLAB编译器将M文件生成可执行文件或链接库的过程是完全自动的。只要源程序是M文件,就可以采用编译命令mcc进行程序的编译。利用mcc命令可以生成独立的可执行程序,也可以生成动态链接库。关于mcc命令的详细说明,用户可以在MATLAB的命令行窗口输入:help mcc进行查看。
PS:直接执行:!file.exe;
在MATLAB中,提供了图形化的编译工具deploytool,在命令窗口输入:help deploytool,可以查看deploytool的功能。在MATLAB的命令行窗口输入:deploytool后将启动该工具,可以在M文件所在的文件夹内新建工程文件,默认为: Untitled1.prj,也可以打开现有的工程文件。命令行工具mcc在运行时,默认产生和M文件同名的工程文件,后缀为.prj,可以用deploytool直接打开。
为了能够运行MATLAB编译产生的可执行文件,用户的计算机上面必须安装MCR。 MCR默认存放在MATLAB的根目录下的ltoolboxlcompilerldeploylwin32文件夹中。
2.VS与MATLAB配置及测试Demo
类似于opencv的配置;附加依赖项添加:libmat.lib、libeng.lib、libmx.lib,可执行文件目录:F:\Matlab2016b\bin\win64,包含目录:F:\Matlab2016b\extern\include,库目录:F:\Matlab2016b\extern\lib\win64\microsoft;添加环境变量;
如果下一步Demo报错,则复制相关缺失的dll到系统盘下的system32文件夹下;
#include <engine.h>
#include <iostream>
const int BUFFER_SIZE = 1024;
char buffer[BUFFER_SIZE];
void test()
{
Engine* ep;
mxArray *x1 = NULL;
mxArray *y1 = NULL;
if ((ep = engOpen("")) == NULL)
{
std::cout << "Engine Fail" << std::endl;
}
engOutputBuffer(ep, buffer, BUFFER_SIZE);
std::cout << "Init Success" << std::endl;
double x[5] = { 1.0, 2.5,3.7,4.4,5.1 };
double y[5] = { 3.3,4.7,9.6,15.6,21.3 };
x1 = mxCreateDoubleMatrix(1, 5, mxREAL);
y1 = mxCreateDoubleMatrix(1, 5, mxREAL);
memcpy((void *)mxGetPr(x1), (void *)x, sizeof(x));
memcpy((void *)mxGetPr(y1), (void *)y, sizeof(y));
engPutVariable(ep, "x", x1);
engPutVariable(ep, "y", y1);
engEvalString(ep, "plot(x,y)");
engClose(ep);
}
void main()
{
test();
}
博主第一次遇到了无法启动engine引擎的坑,这里藏的雷太多了,首先,要设置matlab.exe的兼容性……
在matlab命令行输入mex -setup;然后,利用cmd进行注册,输入命令如下图(别人那抄过来的,改成自己的路径):
3.Matlab Engine API介绍
(1)引擎的打开
Engine* engOpen(const char* startcmd)
启动Matlab引擎,参数 startcmd 是用来启动 Matlab 引擎的字符串参数,在 Windows 操作系统中只能为 NULL 函数返回值是一个 Engine 类型的指针,它是在 engine.h 中定义的 engine 数据结构。
(2)关闭 Matlab 引擎
int engClose(Engine* ep)
关闭Matlab引擎,参数 ep 代表要被关闭的引擎指针。函数返回值为 0 表示关闭成功,返回 1 表示发生错误。
(3)向 Matlab 发送命令字符串
int engEvalString(Engine* ep, const char* string)
执行Matlab表达式,发送命令让 Matlab 执行,参数 ep 为函数 engOpen 返回的引擎指针,字符串 string 为要 matlab 执行的命令, 函数返回值为 0 表示成功执行,返回 1 说明执行失败(如命令不能被 Matlab 正确解释或 Matlab 引擎已经关闭了)。
int engOutputBuffer(Engine *ep, char *p, int n);
要在 VC 中获得函数 engEvalString 发送的命令字符串被 Matlab 执行后在 matlab 窗口中的输出,可以调用 engOUtputBuffer 函数。参数 ep 为 Matlab 引擎指针, p 为用来保存输出结构的缓冲区, n 为最大保存的字符个数,通常就是缓冲区 p 的大小。该函数执行后,接下来的 engEvalString 函数所引起的命令行输出结果会在缓冲区 p 中保存。如果要停止保存,只需调用代码:engOutputBuffer(ep, NULL, 0) 。
(4)读写 Matlab 数据
从 Matlab 引擎工作空间中获取变量。
mxArray *engGetVariable(Engine *ep, const char *name);
参数 ep 为打开的 Matlab 引擎指针, name 为以字符串形式指定的数组名。函数返回值是指向name 数组的指针,类型为mxArray*。
向 Matlab 引擎工作空间写入变量。
int engPutVariable(Engine *ep, const char *name, const mxArray *mp);
参数 ep 为打开的 Matlab 引擎指针, mp 为指向被写入变量的指针, name 为变量写入后在 Matlab 引擎工作空间中的变量名。函数返回值为 0 表示写入变量成功,返回值为 1 表示发生错误。
(5)调用引擎时显示 / 隐藏 Matlab 主窗口
默认情况下,以engine 方式调用 Matlab 的时候,会打开 Matlab 主窗口,可在其中随意操作。但有时也会干扰应用程序的运行,可用以下设置是否显示该窗口。
int engSetVisible(Engine *ep, bool value);
参数 ep 为打开的 Matlab 引擎指针, value 为是否显示的标志,取值 true (或 1 )表示显示 Matlab 窗口,取值 false (或 0 )表示隐藏 Matlab 窗口。函数返回值为 0 表示设置成功,为 1 表示有错误发生。
要获得当前 Matlab 窗口的显示 / 隐藏情况,可以调用函数:
int engGetVisible(Engine *ep, bool *value);
参数 ep 为打开的 Matlab 引擎指针, Value 为用来保存显示 / 隐藏情况的变量(采用指针方式传递)。函数返回值为 0 表示获取成功,为 1 表示有错误发生。
(6)数据类型 mxArray 的操作
在上面的 Matlab 引擎函数中,所有与变量有关的数据类型都是 mxArray 类型。数据结构 mxArray 以及大量的 mx 开头的函数,广泛用于 Matlab 引擎程序和 Matlab C 数学库中。 mxArray 是一种很复杂的数据结构,与 Matlab 中的 array 相对应,我们只需熟悉 Matlab 的 array 类型和几个常用的 mxArray 函数即可。
在 VC 中,所有和 Matlab 的数据交互都是通过 mxArray 来实现的,在使用 mxArray 类型的程序中,应包含头文件 matrix.h ,不过在引擎程序中,一般会包含头文件 engine.h ,该文件里面已经包含了 matrix.h ,因此无需重复包
Matlab 有很多种变量类型,对应于每种类型,基本上都有一个函数用于创建,但它们都有相同的数据结构,就是 mxArray 。数组的建立采用mxCreatexxx 形式的函数,例如新建一个double 类型数组,可用函数mxCreateDoubleMatrix ,函数形式如下:
mxArray *mxCreateDoubleMatrix(int m, int n, mxComplexity ComplexFlag);
参数 m 和 n 为矩阵的行数和列数。 ComplexFlag 为常数,用来区分矩阵中元素是实数还是复数,取值分别为 mxREAL 和 mxCOMPLEX 。
要删除一个数组mxDestroyArray ,该函数声明如下:
void mxDestroyArray(mxArray *array_ptr);
参数 array_ptr 为要删除的数组指针。
创建一个字符串类型并初始化为 str 字符串:
mxArray *mxCreateString(const char *str);
要获得 mxArray 数组每一维上元素的个数,可以用 mxGetM 和 mxGetN 函数。其中 mxGetM 用来获得数组第一维的元素个数,对于矩阵来说就是行数:
int mxGetM(const mxArray *array_ptr); // 返回 array_ptr 对应数组第一维的元素个数(行数)
int mxGetN(const mxArray *array_ptr); // 返回 array_ptr 对应数组其它维的元素个数,对于矩阵来说是列数。对于多维数组来说是从第 2 维到最后一维的各维元素个数的乘积。
要获得某一特定维的元素个数,则要用函数:
const int *mxGetDimensions(const mxArray *array_ptr);
该函数返回array_ptr 各维的元素个数保存在一个int 数组中返回。对于常用的矩阵来说,用 mxGetM 和 mxGetN 两个函数就可以了。
另外还可以通过mxGetNumberOfDimensions 来获得数组的总的维数,用 mxSetM 、 mxSetN 设置矩阵的行数和列数,函数说明如下:
int mxGetNumberOfDimensions(const mxArray *array_ptr); // 返回数组的维数
void mxSetM(mxArray *array_ptr, int m); // 设置数组为 m 行
void mxSetN(mxArray *array_ptr, int n); // 设置数组为 n 列
在对 mxArray 类型的变量进行操作之前,可以验证以下其中的数组的数据类型,比如是否为double 数组、整数、字符串、逻辑值等,以及是否为某种结构、类、或者是特殊类型,比如是否为空数组,是否为 inf 、 NaN 等。常见的判断函数有:
bool mxIsDouble(const mxArray *array_ptr);
bool mxIsComplex(const mxArray *array_ptr);
bool mxIsChar(const mxArray *array_ptr);
bool mxIsEmpty(const mxArray *array_ptr);
bool mxIsInf(double value);
对于常用的 double 类型的数组,可以用mxGetPr 和 mxGetPi 两个函数分别获得其实部和虚部的数据指针,这两个函数的声明如下:
double *mxGetPr(const mxArray *array_ptr); // 返回数组 array_ptr 的实部指针
double *mxGetPi(const mxArray *array_ptr); // 返回数组 array_ptr 的虚部指针
这样,就可以通过获得的指针对 mxArray 类型的数组中的数据进行读写操作。例如可以用函数 engGetVariable 从 Matlab 工作空间读入 mxArray 类型的数组,然后用 mxGetPr 和 mxGetPi 获得数据指针,对并其中的数据进行处理,最后调用 engPutVariable 函数将修改后的数组重新写入到 Matlab 工作空间。