matlab和c++混合编程


前言

1 需求分析
在C++开发过程中,可能需要C++和MATLAB混合编程,比如:别人只会MATLAB,需要和我们的C++一起运行;或者有部分MATLAB/Simulink开发的模块或者函数,需要快速整合到C++中。那么通常我们会考虑以MATLAB为主程序调用C++代码或者以C++为主程序调用MATLAB代码的方式。

2 C++/MATLAB混合编程方式
MATALB官方提供了多种MATLAB与其他语言混合编程的方法,对于C++与MATLAB的混合编程包括下面两种:

【1】C++调用MATLAB

  1. 用于C++的MATLAB引擎API
  2. 将MATLAB函数编译为C++动态库

【2】MATLAB调用C/C++

  1. MATLAB调用C++ MEX函数
  2. 通过calllib调用C动态库

MATLAB引擎API主要通过matlab::engine::MATLABEngine类和matlab::data::Array等类完成MATLAB的接口功能,其实C++ MEX函数本质上也是调用MATLAB引擎API的接口。后面将介绍以C++最为主程序,调用MATLAB引擎的方法。

一、C++调用matlab的引擎配置说明

【1】vc++目录——库目录和包含目录配置

包含目录:E:\matlab\extern\include
库目录:E:\matlab\extern\lib\win64\microsoft

在这里插入图片描述
【2】链接器->附加依赖项——填写这些lib

libeng.lib
libmx.lib
libmex.lib
mclmcrrt.lib
libeng.lib
libmat.lib
mclmcr.lib
lib*.lib(自己生成的lib文件,调用引擎方法不需要)

方法1
在这里插入图片描述
`方法2
在这里插入图片描述

【3】常规处配置`

在这里插入图片描述
【4】我的电脑环境变量配置

E:\matlab\extern\lib\win64\microsoft
E:\matlab\extern\bin\win64

在这里插入图片描述

测试代码

// CMatlab.cpp : 定义控制台应用程序的入口点。
//
//#include "stdafx.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "engine.h"  // add header file

// import necessary lib
#pragma comment( lib, "libeng.lib")
#pragma comment( lib, "libmx.lib")
#pragma comment( lib, "libmat.lib")

int main(void)
{
	Engine *ep;

	// open engine
	if (!(ep = engOpen("\0")))
	{
		fprintf(stderr, "\nCan't start MATLAB engine\n");
		return EXIT_FAILURE;
	}

	// generate variables
	int Nsample = 50;
	const double PI = 3.1415926;
	double *t = new double[Nsample];

	for (int i = 0; i < Nsample; i++)
	{
		t[i] = i * 2 * PI / Nsample;
	}

	mxArray *T = NULL, *result = NULL;
	T = mxCreateDoubleMatrix(1, Nsample, mxREAL);
	memcpy((void *)mxGetPr(T), (void *)t, Nsample * sizeof(t[0]));

	engPutVariable(ep, "T", T);   // put data to engine

	// execute matlab operations
	engEvalString(ep, "Y=sin(T);");
	engEvalString(ep, "plot(T,Y);");
	engEvalString(ep, "title('y=sin(t)');");
	engEvalString(ep, "xlabel('t');");
	engEvalString(ep, "ylabel('y');");

	printf("Hit return to continue\n");
	fgetc(stdin);

	// clean operation(don't forget!!!)
	mxDestroyArray(T);
	engEvalString(ep, "close;");

	// close engine
	engClose(ep);

	return EXIT_SUCCESS;
}

二、C++调用matlab引擎实现数据传输与返回

【注意】在第一章的基础上增加几步如下:
【1】为了便于调用m文件,在适合的路径下新建文件夹,然后打开matlab将该文件夹添加到搜索路径中
在这里插入图片描述
【2】之后将需要调用的m文件粘贴到该路径。为了测试,在该路径下新建一个MatrixTranspose.m用于输出矩阵的转置
matlab代码

function T = MatrixTranspose(mat)
T = mat';
end

C++代码

// 2017-06-10 by LSS

#include "engine.h"
#include <iostream>
using namespace std;

int SetMat(const char *VarName, void *mat, int M, Engine *engine)
{
	mxArray *matArray = mxCreateDoubleMatrix(M, M, mxREAL);
	memcpy(mxGetPr(matArray), mat, M*M * sizeof(double));
	int status = engPutVariable(engine, VarName, matArray);
	mxDestroyArray(matArray);
	return status;
}

void GetMat(const char *VarName, void *mat, int M, Engine *engine)
{
	memcpy(mat, mxGetPr(engGetVariable(engine, VarName)), M*M * sizeof(double));
}

int main()
{
	cout << "Matlab Engine opening..." << endl << endl;
	Engine *engine = engOpen(NULL);
	if (!engine)
	{
		cout << "Failed to start matlab engine" << endl;
		system("pause");
		exit(1);
	}
	engSetVisible(engine, true);

	cout << "input:" << endl;
	const int M = 6;
	double mat[M][M];
	for (int i = 0; i < M; i++)
	{
		for (int j = 0; j < M; j++)
		{
			mat[i][j] = 3 * i + j;
			cout << mat[i][j] << "\t";
		}
		cout << endl;
	}
	cout << endl;

	SetMat("mat", (void *)mat, M, engine);
	engEvalString(engine, "mat = MatrixTranspose(mat);");
	GetMat("mat", (void *)mat, M, engine);

	cout << "output:" << endl;
	for (int i = 0; i < M; i++)
	{
		for (int j = 0; j < M; j++)
		{
			cout << mat[i][j] << "\t";
		}
		cout << endl;
	}

	engEvalString(engine, "peaks");
	system("pause");
	//engEvalString(engine, "exit");
	//engClose(engine);
	return 0;
}

结果如下
在这里插入图片描述
解析
首先添加了matlab引擎头文件后,Engine *engine = engOpen(NULL);调用库函数打开matlab引擎,engSetVisible(engine, true);用于设置matlab窗口是否可见,设为false时可隐藏所有matlab窗口,所以需要设为true以显示绘图窗口。在初始化一个6×6方阵后开始调用引擎。
数据的传输比较麻烦,所以简单封装了一下子函数SetMat()和GetMat()用于向matlab的工作区进行变量赋值和获取变量值。主要通过mxArray数据结构作为中间变量进行传输,mxCreateDoubleMatrix(M, M, mxREAL)用于创建M×M维的double型矩阵,mxREAL指定数据为实数,可以改为mxCOMPLEX以指定为复数。创建完成后通过memcpy()将数组数据拷贝到矩阵中,随后通过engPutVariable()库函数将矩阵赋值到字符串指定名称的matlab变量中,完成赋值操作。类似的,通过engGetVariable()库函数获取工作区中指定名称的matlab变量的指针,然后通过memcpy()拷贝数据到数组中,完成矩阵变量值的获取。
只要是可以通过命令行执行的指令都可以通过matlab引擎执行,调用库函数engEvalString(engine, “mat = MatrixTranspose(mat);”);时相当于在matlab命令行输入字符串并执行,这里是调用MatrixTranspose.m并传入mat矩阵,执行后返回转置后的矩阵并赋值给mat矩阵变量。
需要注意的是后面两行注释掉的代码,engEvalString(engine, “exit”);执行退出命令以关闭所有的matlab窗口,engClose(engine);用于关闭引擎,注释掉是为了更方便地进行调试,不需要再初始化引擎以提升程序运行速度。此外如果每次运行都关闭引擎重新初始化,会导致在修改程序后首次运行时memcpy()引起程序崩溃,再次运行程序才能正常工作,所以在频繁修改代码时不需要关闭matlab引擎。

2.1附加小例子1

C++与matlab引擎联调计算三次多项式的根
原理
在这里插入图片描述

//Bexm040301.c]
#include <windows.h>			//定义编写Windows程序所必须的数据类型、宏、函数等
#include <stdlib.h>			//定义通用数据类型、宏、函数等
#include <stdio.h>			//用于标准I/O程序定义和申明的头文件
#include "engine.h"			//定义MATLAB引擎应用中所必需的数据类型、宏、函数等
#include<iostream>
using namespace std;
int main(HANDLE hInstance, HANDLE hPrevInstance, LPSTR  lpszCmdLine, int nCmdShow)
{
	Engine *ep;						//定义ep为MATLAB引擎的指针
	mxArray *P = NULL, *r = NULL;		//定义2个空mxArray变量
	char buffer[256];				//定义容量为256的缓冲区
	double poly[4] = { 1,0,-2,5 };		//定义双精度变量,含4个元素的多项式系数。
	cout << "启动matlab引擎中" << endl;
	if (!(ep = engOpen(NULL))) //启动本机MATLAB引擎,如果出错则退出程序。
	{
		fprintf(stderr, "\nCan't start MATLAB engine\n");
		return EXIT_FAILURE;
	}
	cout << "启动matlab引擎结束" << endl;
	cout << "C++与matlab联调中" << endl;
	P = mxCreateDoubleMatrix(1, 4, mxREAL);	//令P为所创(1X4)双精度实矩阵的指针
	//把poly源缓冲区中内容复制到P所指mxArray实部的目标缓冲区中
	//待复制的字节数为4个双精度数
	memcpy((char *)mxGetPr(P), (char *)poly, 4 * sizeof(double));

	//把P所指mxArray变量放进ep所指的MATLAB引擎空间,并起名p	
	engPutVariable(ep, "p", P);

	//为ep所指引擎准备buffer所指的长度为256的缓冲区,
	//用于接收engEvalString函数运行之后的屏幕显示结果	
	engOutputBuffer(ep, buffer, 256);

	//命令ep所指引擎对"disp(['多项式   x^3-2x+5   的根']),r=roots(p)"
	//进行串运算,并把计算结果写进buffer所指的缓冲区
	engEvalString(ep, "disp(['多项式   x^3-2x+5   的根']),r=roots(p)");

	//该对话框直接建立在根屏幕上,发布buffer缓冲区中的内容,
	//对话框的名称是“Bexm040301展示MATLAB引擎的应用”
	//该框带一个“确定”按键。只有点击该键才能执行其他过程。
	MessageBox(NULL, buffer, "Bexm040301展示MATLAB引擎的应用", MB_OK);

	engClose(ep);			//关闭ep所指引擎
	mxDestroyArray(P);	
	cout << "C++与matlab联调结束" << endl;
	system("pause");	//释放被mxCreate配置过的P所指动态内存
	return EXIT_SUCCESS;
}

结果
在这里插入图片描述

2.2附加小例子2

Matlab引擎对用户自编M函数文件的调用


//Bexm040302.c
#include <stdlib.h>			//定义通用数据类型、宏、函数等
#include <stdio.h>			//用于标准I/O程序定义和申明的头文件
#include <string.h>
#include "engine.h"			//定义MATLAB引擎应用中所必需的数据类型、宏、函数等
#include<windows.h>    //定义编写windows程序所必须的数据类型、宏、函数等
#include<iostream>
using namespace std;
#define  BUFSIZE 512
int main()
{
	Engine *ep;
	mxArray *Pz = NULL, *result = NULL;
	char buffer[BUFSIZE];
	double zeta[1] = { 30 };		//MATLAB环境外数据示例
	if (!(ep = engOpen(NULL)))
	{
		fprintf(stderr, "\nCan't start MATLAB engine\n");
		return EXIT_FAILURE;
	}
	//-----------------------------------------------------------
	//程序段1:(A)把zeta数据送进MATLAB;(B)利用引擎进行计算。
	//-----------------------------------------------------------
	//创建指针为Pz的(1*1)实型mxArray
	Pz = mxCreateDoubleMatrix(1, 1, mxREAL);
	//把zeta中的全部数据复制到Pz所指mxArray变量中
	memcpy((void *)mxGetPr(Pz), (void *)zeta, sizeof(zeta));
	//把Pz所指mxArray变量送进MATLAB引擎空间,并取名为z
	engPutVariable(ep, "z", Pz);
	//把符合MATLAB语法的命令送进引擎空间执行,执行engly文件
	//engEvalString(ep, "cd D:\\Mywork\\ExampleB\\Bexm040302");   //<28>
	engEvalString(ep, "engly(z);");								//<29>

	printf("按Enter键继续!\n\n");	//在DOS界面显示提示内容
	fgetc(stdin);		//等待键盘输入,在此用来保证图形窗在前台有足够停留时间。
	printf("程序段1运行已经结束。下面处于程序段2运行过程中!\n");
	mxDestroyArray(Pz);						//释放Pz所占内存
	engEvalString(ep, "close;");			//关闭MATLAB引擎
	//-------------------------------------------------------------------------
	/*程序段2:	由于DOS界面成为MATLAB引擎的工作界面。(A)用户可以在该DOS环境下输入任何符合MATLAB语法的命令,并看到相应结果;(B)假如用户
	要关闭该程序,一定要创建数值变量Exit 。*/
	//-------------------------------------------------------------------------
	engOutputBuffer(ep, buffer, BUFSIZE);
	//为ep所指引擎配置buffer所指的长度为BUFSIZE的缓冲区,
	//准备承接MATLAB的输出。
	while (result == NULL) {
		char str[BUFSIZE];
		printf("注意:\n");
		printf("? 此界面上,可输入任何MATLAB命令。\n");
		printf("? 若想退出,请对Exit变量赋任何数值。\n");
		printf(">> ");
		fgets(str, BUFSIZE - 1, stdin);		//获得用户输入的字符串str
		engEvalString(ep, str);				//把从界面输入的串str送进引擎计算
		printf(" %s", buffer);				//把计算结果显示在界面上

		//从引擎空间中读出名为Exit的变量
		if ((result = engGetVariable(ep, "Exit")) == NULL)
			printf("可继续运行!\n");
	}
	printf("运行结束!\n");
	mxDestroyArray(result);
	engClose(ep);
	return EXIT_SUCCESS;
}

在这里插入图片描述
在这里插入图片描述

2.3附加小例子3

// Bexm040401.cpp : 定义控制台应用程序的入口点。
//

//#include "stdafx.h"
#include "engine.h"			//定义MATLAB引擎应用中所必需的数据类型、宏、函数等
#include "mat.h"			//定义MAT文件接入和创建方法的头文件
#include <windows.h>		//定义编写Windows程序所必须的数据类型、宏、函数等
#include<iostream>
using namespace std;

int main(int argc, char * argv[])
{
	double * b, a[9] = { 1,4,7,2,5,8,3,6,9 };
	const char *file = "mymat.mat";
	mxArray *Ain, *Aout, *SV;
	Engine * ep;
	MATFile *mat;
	//------------------数据写入mymat.mat文件后关闭之-------------
	//以“写”方式打开名为file的mymat.mat文件,并为它设定指针mat
	mat = matOpen(file, "w");
	//创建指针为Ain的(3*3)实型mxArray
	Ain = mxCreateDoubleMatrix(3, 3, mxREAL);
	//把a源缓冲区中内容复制到Ain所指mxArray实部的目标缓冲区中
	//待复制的字节数为9个双精度数
	memcpy((char *)mxGetPr(Ain), (char *)a, 9 * sizeof(double));

	//把Ain所指mxArray放进mat所指的mymat.mat文件
	matPutVariable(mat, "z", Ain);
	//关闭mat所指的mymat.mat文件
	matClose(mat);
	//释放Ain所指mxArray缓冲区
	mxDestroyArray(Ain);

	//打开mymat.mat文件并把数据读出,然后送到引擎中计算,最后从引擎中取出并显示
	//--------读mymat.mat文件后的数据,送引擎计算,显示返回结果---------

	//以“读”方式打开名为file的mymat.mat文件,并为它设定指针mat
	mat = matOpen(file, "r");
	//从mat所指MAT文件中读出名为z的mxArray变量,并设指针为Aout。
	Aout = matGetVariable(mat, "z");
	//开启本地MATLAB引擎,若成功便执行以下命令。
	if (ep = engOpen(NULL))
	{
		//把Aout所指mxArray(带变量名z)数据送进MATLAB引擎空间
		engPutVariable(ep, "z", Aout);
		//在引擎空间中求z矩阵的奇异值
		engEvalString(ep, "sv=svd(z);");
		//从引擎空间中获取算得的sv存入SV 所指的mxArray
		SV = engGetVariable(ep, "sv");
		//获取SV所指的mxArray实部的指针b
		b = mxGetPr(SV);
		//在DOS界面上显示“奇异值为”
		printf("奇异值为");
		printf("\n");
		for (int i = 0; i < 3; i++)
		{
			//在同一行中显示所有奇异值
			printf("  %.2f", b[i]);
		}
		//关闭MATLAB引擎
		engClose(ep);
		//关闭mat所指mymat.mat文件
		matClose(mat);
		//释放Aout所占内存
		mxDestroyArray(Aout);
		//释放SV所占内存
		mxDestroyArray(SV);
	}
	else
	{
		//MATLAB引擎开启失败的提示
		printf("Can't open matlab");
	}
	return 0;
}


输出结果
在这里插入图片描述

三、C语言memcpy函数的用法

介绍
memcpy是memory copy的缩写,意为内存复制,在写C语言程序的时候,我们常常会用到它。它的函原型如下:

void *memcpy(void *dest, const void *src, size_t n);

它的功能是从src的开始位置拷贝n个字节的数据到dest。如果dest存在数据,将会被覆盖。memcpy函数的返回值是dest的指针。memcpy函数定义在string.h头文件里。
例子
1.将一个字符串数据复制到一块内存。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define N 10
int main(void)
{
    char* target=(char*)malloc(sizeof(char)*N);
    memcpy(target,"0123456789",sizeof(char)*N);
    puts(target);
    free(target);
    return 0;
}

编译,运行,将输出:0123456789
2.将一个字符串数据复制到一块内存的指定位置。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define N 10
int main(void)
{
    char* target=(char*)malloc(sizeof(char));
    for(int i=0;i<N;i++){
        memcpy(target+i,"a",sizeof(char));
    }
    puts(target);
    free(target);
    return 0;
}

编译,运行,将输出:aaaaaaaaaa
3.数据覆盖

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define N 10
int main(void)
{
    char* target=(char*)malloc(sizeof(char)*N);
    memcpy(target,"0123456789",sizeof(char)*N);
    puts(target);
    memcpy(target,"aaaaa",sizeof(char)*(N-5));
    puts(target);
    free(target);
    return 0;
}

编译,运行,将输出:

0123456789
aaaaa56789

四、c++中调用matlab引擎计算

4.1什么是Matlab引擎

所谓Matlab引擎(engine),是指一组Matlab提供的接口函数,支持C/C++、Fortran等语言,通过这些接口函数,用户可以在其它编程环境中实现对Matlab的控制。可以主要功能有:
★ 打开/关闭一个Matlab对话;
★ 向Matlab环境发送命令字符串;
★ 从Matlab环境中读取数据;
★ 向Matlab环境中写入数据。
与其它各种接口相比,引擎所提供的Matlab功能支持是最全面的。通过引擎方式,应用程序会打开一个新的Matlab进程,可以控制它完成任何计算和绘 图操作。对所有的数据结构提供100%的支持。同时,引擎方式打开的Matlab进程会在任务栏显示自己的图标,打开该窗口,可以观察主程序通过 engine方式控制Matlab运行的流程,并可在其中输入任何Matlab命令。
实际上,通过引擎方式建立的对话,是将Matlab以ActiveX控件方式启动的。在Matlab初次安装时,会自动执行一次:

matlab /regserver

将自己在系统的控件库中注册。如果因为特殊原因,无法打开Matlab引擎,可以在Dos命令提示符后执行上述命令,重新注册。

4.2引擎API详解

在调用Matlab引擎之前,首先应在相关文件中加入一行:#include “enging.h”,该文件包含了引擎API函数的说明和所需数据结构的定义。可以在VC中调用的引擎函数分别如下:

4.2.1引擎的打开和关闭

【1】engOpen-打开Matlab engine
函数声明:

Engine *engOpen(const char *startcmd);
参数startcmd是用来启动Matlab引擎的字符串参数,在Windows操作系统中只能为NULL

函数返回值是一个Engine类型的指针,它是在engine.h中定义的engine数据结构。

【2】EngClose-关闭Matlab 引擎
函数声明:

int engClose(Engine *ep);
参数ep代表要被关闭的引擎指针。

函数返回值为0表示关闭成功,返回1表示发生错误。
例如,通常用来打开/关闭Matlab引擎的代码如下:

Engine *ep; //定义Matlab引擎指针。
if (!(ep=engOpen(NULL))) //测试是否启动Matlab引擎成功。
{
MessageBox("Can't start Matlab engine!" );
exit(1);
}
........
engClose(ep); //关闭Matlab引擎。

4.2.2向Matlab发送命令字符串

engEvalString-发送命令让Matlab执行。
函数声明:

int engEvalString(Engine *ep, Const char *string);
参数ep为函数engOpen返回的引擎指针,字符串string为要matlab执行的命令。

函数返回值为0表示成功执行,返回1说明执行失败(如命令不能被Matlab正确解释或Matlab引擎已经关闭了)。
例如:

//向Matlab引擎发送画图命令。plot为Matlab的画图函数,参见Matlab相关文档。
	engEvalString(ep, "plot(xx, yy); ");

4.3获取Matlab命令窗口的输出

要在VC中获得函数engEvalString发送的命令字符串被Matlab执行后在matlab窗口中的输出,可以调用engOUtputBuffer函数。
函数声明:

int engOutputBuffer(Engine *ep, char *p, int n);
参数ep为Matlab引擎指针,p为用来保存输出结构的缓冲区,n为最大保存的字符个数,通常就是缓冲区p的大小。

该函数执行后,接下来的 engEvalString函数所引起的命令行输出结果会在缓冲区p中保存。如果要停止保存,只需调用代码:engOutputBuffer(ep, NULL, 0)。

4.4读写Matlab数据

4.4.1从Matlab引擎工作空间中获取变量

mxArray *engGetVariable(Engine *ep, const char *name);
参数ep为打开的Matlab引擎指针,name为以字符串形式指定的数组名。

函数返回值是指向name数组的指针,类型为mxArray*(mxArray数据类型在下面详细简介)。

4.4.2向Matlab引擎工作空间写入变量

int engPutVariable(Engine *ep, const char *name, const mxArray *mp);
参数ep为打开的Matlab引擎指针,mp为指向被写入变量的指针,name为变量写入后在Matlab引擎工作空间中的变量名。
函数返回值为0表示写入变量成功,返回值为1表示发生错误。

4.5调用引擎时显示/隐藏Matlab主窗口

【1】默认情况下,以engine方式调用Matlab的时候,会打开Matlab主窗口,可在其中随意操作。但有时也会干扰应用程序的运行,可用以下设置是否显示该窗口。

int engSetVisible(Engine *ep, bool value);
参数ep为打开的Matlab引擎指针,value为是否显示的标志,取值true(或1)表示显示Matlab窗口,取值false(或0)表示隐藏Matlab窗口。

函数返回值为0表示设置成功,为1表示有错误发生。
【2】要获得当前Matlab窗口的显示/隐藏情况,可以调用函数:

int engGetVisible(Engine *ep, bool *value);
参数ep为打开的Matlab引擎指针,Value为用来保存显示/隐藏情况的变量(采用指针方式传递)。

函数返回值为0表示获取成功,为1表示有错误发生。

4.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,因此无需重复包含。

4.6.1创建和清除mxArray型数据

Matlab有很多种变量类型,对应于每种类型,基本上都有一个函数用于创建,但它们都有相同的数据结构,就是mxArray。

【1】数组的建立采用mxCreatexxx形式的函数,例如新建一个double类型数组,可用函数mxCreateDoubleMatrix,函数形式如下:

mxArray *mxCreateDoubleMatrix(int m, int n, mxComplexity ComplexFlag);
参数m和n为矩阵的函数和列数。ComplexFlag为常数,用来区分矩阵中元素是实数还是复数,取值分别为mxREAL和mxCOMPLEX。

例如,创建一个3行5列的二维实数数组,可用如下语句:

mxArray *T = mxCreateDoubleMatrix(3, 5, mxREAL);

【2】要删除一个数组mxDestroyArray,该函数声明如下:

void mxDestroyArray(mxArray *array_ptr);
参数array_ptr为要删除的数组指针。

例如,要删除上面创建的数组T,可用如下语句:

mxDestroyArray(T);

类似的创建函数还有:

mxArray *mxCreateString(const char *str);
创建一个字符串类型并初始化为str字符串。

一般的在VC与Matlab交互中,以上两种类型就够了,其它类型数组的创建这里不再介绍。

4.6.2管理mxArray数据大小

要获得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列

4.6.3判断mxArray数组类型

在对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);
......

这些函数比较简单,意义自明,不再解释。

4.6.4管理mxArray数组的数据

对于常用的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工作空间。具体实现见第5节程序实例。

4.7程序实例

对大部分软件研发人员来说利用VC编程方便、高效,但是要显示数据图形就不那么容易了,这时候不防借助Matlab引擎辅助画图做数据分析。下面通过实例演示如何利用VC调用Matlab绘图,程序的主要功能是在VC中对数组x计算函数值y=sin(x) ±log(x),然后调用Matlab绘制y对x的图形。
在VC中新建工程,编写代码如下:

#include <iostream>
#include <math.h>
#include "engine.h"
using namespace std;
int main()
{
	const int N = 50;
	double x[N], y[N];
	int j = 1;
	for (int i = 0; i < N; i++) //计算数组x和y
	{
		x[i] = (i + 1);
		y[i] = sin(x[i]) + j * log(x[i]); //产生-之间的随机数赋给xx[i];
		j *= -1;
	}
	cout << "加载matlab引擎中..." << endl;
	Engine *ep; //定义Matlab引擎指针。
	if (!(ep = engOpen(NULL))) //测试是否启动Matlab引擎成功。
	{
		cout << "Can't start Matlab engine!" << endl;
		exit(1);
	}
	cout << "加载matlab引擎结束" << endl;
	cout << "matlab引擎处理中..." << endl;
	//定义mxArray,为行,N列的实数数组。
	mxArray *xx = mxCreateDoubleMatrix(1, N, mxREAL);
	mxArray *yy = mxCreateDoubleMatrix(1, N, mxREAL); //同上。

	memcpy(mxGetPr(xx), x, N * sizeof(double)); //将数组x复制到mxarray数组xx中。
	memcpy(mxGetPr(yy), y, N * sizeof(double)); //将数组x复制到mxarray数组yy中。

	engPutVariable(ep, "xx", xx); //将mxArray数组xx写入到Matlab工作空间,命名为xx。
	engPutVariable(ep, "yy", yy); //将mxArray数组yy写入到Matlab工作空间,命名为yy。

	//向Matlab引擎发送画图命令。plot为Matlab的画图函数,参见Matlab相关文档。
	engEvalString(ep, "plot(xx, yy); ");

	mxDestroyArray(xx); //销毁mxArray数组xx和yy。
	mxDestroyArray(yy);
	cout << "matlab引擎结束" << endl;
	cout << "Press any key to exit!" << endl;
	//cin.get();
	engClose(ep); //关闭Matlab引擎。
	cout << "关闭matlab引擎" << endl;
	system("pause");
	return 0;
}

输出结果:
在这里插入图片描述
本文详细的介绍了Matlab引擎使用方法并演示了一个简单的利用VC调用Matlab画图的程序实例。大多数时候,程序员可以利用Matlab强大的数 据读写、显示能力和VC编程的高效率。例如,在Matlab中要读入一幅任意格式的图像均只需一条命令i=imread(‘test.jp’);图像数据 矩阵便存放在了二维数组i中,可以通过VC读入该数组进行相关处理再调用Matlab显示,这种混合编程方式能大大提高工作效率。

当然,利用VC编译的Matlab引擎程序,运行环境中还必须Matlab的支持,如果要编译完全脱离Matlab的程序,可采用其它方式,如利用第三方Matcom程序编译独立的可执行程序等。

五、Qt与matlab混合编程

更新中

六、C++和matlab混合编程实现小波变换

C++代码

// 2017-06-10 by LSS

#include "engine.h"
#include <iostream>
#include<Windows.h>
using namespace std;

int SetMat(const char *VarName, void *mat, int M, Engine *engine)
{
	mxArray *matArray = mxCreateDoubleMatrix(1, M, mxREAL);
	memcpy(mxGetPr(matArray), mat, M * sizeof(double));
	int status = engPutVariable(engine, VarName, matArray);
	mxDestroyArray(matArray);
	return status;
}

void GetMat(const char *VarName, void *mat, int M, Engine *engine)
{
	memcpy(mat, mxGetPr(engGetVariable(engine, VarName)), M * sizeof(double));
}

int main()
{
	cout << "Matlab Engine opening..." << endl;
	Engine *engine = engOpen(NULL);
	if (!engine)
	{
		cout << "Failed to start matlab engine" << endl;
		system("pause");
		exit(1);
	}
	//engSetVisible(engine, true);
	cout << "Matlab Engine opening end" << endl;
	cout << "input:" << endl;
	DWORD startTime = GetTickCount();//计时开始
	const int M = 6;
	double mat[M] = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 };
	for (int i = 0; i < M; i++)
	{

		cout << mat[i] << "\t";

		//cout << endl;
	}
	cout << endl;

	SetMat("mat", (void *)mat, M, engine);
	engEvalString(engine, "mat = energy1(mat);");
	GetMat("mat", (void *)mat, M, engine);

	cout << "output:" << endl;
	for (int i = 0; i < M; i++)
	{
		
		cout << mat[i] << "\t";
		
		//cout << endl;
	}
	DWORD endTime = GetTickCount();//计时结束
	cout << "The run time is:" << endTime - startTime << "ms" << endl;
	//engEvalString(engine, "peaks");
	system("pause");
	//engEvalString(engine, "exit");
	//engClose(engine);
	return 0;
}

matlab建立energy1.m文件,注意函数名要与文件名相同

function E=energy1(A)
wpt=wpdec(A,3,'db1'); %利用db1波对正常信号s1进行3层分解
E = wenergy(wpt);
end

在这里插入图片描述

  • 33
    点赞
  • 67
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
MATLAB和C之间的接口编程是指在MATLAB环境中编写完程序后,将其转换为可以供C语言调用的动态链接库(DLL)的过程。这样做的好处是可以将MATLAB的强大计算能力与C语言的高效性能相结合,实现更复杂的功能。具体步骤如下: 1. 首先,确保你已经安装了MATLAB Runtime(MCR),它是在没有安装MATLAB的情况下运行MATLAB编译器生成的应用程序所必需的。 2. 在MATLAB环境中编写完程序后,将其转换为DLL文件。这可以通过使用MATLAB Compiler工具来实现。你可以在MATLAB Compiler的官方网站上下载该工具。 3. 将需要转换的MATLAB函数文件添加到MATLAB Compiler中,并指定输出格式为DLL。注意,MATLAB只能将函数文件转换为DLL,而不是整个MATLAB脚本文件。因此,确保你的代码是以函数形式编写的。 4. 运行转换操作,MATLAB Compiler将会自动生成DLL文件和其他相关文件。一般情况下,你只需要打开生成的"for_redistribution_files_only"文件夹,即可找到你想要的DLL文件。 通过上述步骤,你就可以成功将MATLAB代码转换为C语言可以调用的DLL文件,以便在其他C程序中使用MATLAB的功能。这样你可以在C语言环境中调用该DLL文件,实现与MATLAB相同的功能。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [MATLABC++接口(上)(看这一篇足够了!!!)](https://blog.csdn.net/qq_25791387/article/details/120449617)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值