学习matlab(十二)——与C/C++混合编程(Engine配置)

本文介绍了如何在MATLAB 2016环境下,结合VS2015进行数据可视化,并探讨了MATLAB编译器的使用,包括生成可执行文件和动态链接库。此外,详细讲解了MATLAB Engine API的使用,包括打开、关闭引擎,发送命令,读写变量等操作,以及与C++的集成示例。
摘要由CSDN通过智能技术生成

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

https://blog.csdn.net/shouzang/article/details/80795945?utm_medium=distribute.pc_feed_404.none-task-blog-BlogCommendFromBaidu-2.nonecase&dist_request_id=&depth_1-utm_source=distribute.pc_feed_404.none-task-blog-BlogCommendFromBaidu-2.nonecas

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 工作空间。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值