C++与MATLAB混合编程总结

版权声明:转载请注明出处。 https://blog.csdn.net/sinich__eveen/article/details/86557705

目录

1.  前言

2. 学会使用“方式(1)”,参考以下资料即可:

3. 学会使用“方式(2)”,参考以下资料即可:

3.1 以下是一些我做毕业设计用到的代码,可以参考一下:

3.1.1 参考代码1:

3.1.2 参考代码2: 



1.  前言

因为毕业设计的需求,研究了一下,C++如何与MATLAB一起混合编程,中间走了一些弯路,这里总结一下。

我用的主要是C++如何调用MATLAB,而没有涉及MATLAB如何调用C++。

注意:根据摸索的经验,比较兼容的组合是:“Microsoft Visual Stuido Enterprise 2015" + "Matlab R2015b win 32位”。其它版本的组合可能会出现这问题,那问题,你也可以自己摸索一下。用32位MATLAB的原因:VS的工程一般都是32位调试,而32位MATLAB封装成的“dll”文件是32位的,放到VS里边,都是32位,正好运行。而64位MATLAB封装的“dll”文件是64位,如果VS工程是32位,则会提示出错。

链接:Microsoft Visual Stuido Enterprise 2015

链接:Matlab R2015b win 32位

C++调用MATLAB,主要有两种方式:(1)调用MATLAB生成的【dll】文件,对MATLAB没有那么强的依赖,可以脱离MATLAB独立运行。(2)C++调用MATLAB引擎,这个必须要有MATLAB。本质是通过C++把MATLAB命令字符串送到MATLAB的【command windows】里边,然后MATLAB运行该命令。

“方式(1)”的使用场景举例:MATLAB里边有很多封装好的函数,可能有些自己用C++不会写,这时候可以把这些函数封装成【dll】文件,放到C++里边调用。

“方式(2)”的使用场景举例:C++跑出了数据,直接调用MATLAB绘图,查看图形结果,不用把数据再导到MATLAB中画图。

2. 学会使用“方式(1)”,参考以下资料即可:

资料1:https://www.cnblogs.com/yangang92/p/5312991.html

资料2:https://www.cnblogs.com/AlgrithmsRookie/p/7049467.html

资料3:https://blog.csdn.net/hong__fang/article/details/43307701

资料4:https://blog.csdn.net/cuiguanjun/article/details/52828192

资料5:http://blog.sina.com.cn/s/blog_b3facf740101e3c7.html

因为这个方法涉及到"dll”文件,不方便在这里放例子。看完上述资料,手动操作一下,应该懂得差不多了。应该懂得如何封装成"dll“文件,并知道如何在C++里边写接口函数,调用”dll“文件了。

3. 学会使用“方式(2)”,参考以下资料即可:

资料1:http://dev.yesky.com/300/2343300.shtml

资料2:https://www.cnblogs.com/Vonng/p/4232586.html

3.1 以下是一些我做毕业设计用到的代码,可以参考一下:

3.1.1 参考代码1:

C++读取MATLAB的.m文件,并发送到MATLAB运行。(头文件自己记得添加,这里只是主体代码)

//C++读取MATLAB的.m文件,并发送到MATLAB运行


//打开MATLAB引擎
Engine *matlabEngine;    //定义MATLAB引擎指针
if (!(matlabEngine = engOpen(NULL)))    //测试是否启动Matlab引擎成功
{
    cout << "Can't start Matlab engine!" << endl;
    exit(1);
}


//读取文件中有效命令到"matlabCode",并发送到MATLAB
ifstream fin;
fin.open("voronoiData.m", ios_base::in);
string matlabCode;
string buf;
string zhuShi = "%";    //** 用于查找是否有注释
string::size_type index;

while (getline(fin, buf))
{
    if (buf.empty())    //跳过文件中的空行
    {
        fin.clear();
        buf.erase();    //遇到空行,输入流被阻断,需要重置,以便后续读取
    }
    else    //判断某行是否有注释,如果有,去掉注释内容
    {
        index = buf.find(zhuShi);    //查找该行是否有注释,依据MATLAB注释关键字"%"定位
        if (index == string::npos)
        {
            buf += ";";
            matlabCode += buf;
            buf.erase();
        }
        else
        {
            string temp(buf, 0, index);    //去掉注释内容
            buf.erase();
            temp += ";";
            matlabCode += temp;
        }
    }
}
engEvalString(matlabEngine, matlabCode.c_str());    //命令发送到MATLAB
fin.close();    //关闭文件

3.1.2 参考代码2: 

用C++编写代码实现MATLAB的【plot、bar】函数。

Plot.h

#pragma once

#include<vector>
#include"engine.h"
#include"CSBS.h"
#include<string>

using std::string;
using std::vector;

/*-----------------------------------------MATLAB Plot函数-----------------------------------------*/

void Plot(vector<double>& x_vec, vector<double>& y_vec, string plotCommand, Engine* matlabEngine);

/*-----------------------------------------------------------------------------------------------------*/


/*----------------------------------------------画资源分配圈-----------------------------------------*/

void CircleCenterPoint(double x, double y, Engine* matlabEngine);

/*-----------------------------------------------------------------------------------------------------*/


/*-----------------------------------------画出组内CSBS的R_sa圈------------------------------------*/

void CircleCSBS(vector<CSBS>& GroupCSBS_vec, double R_sa, Engine* matlabEngine);

/*-----------------------------------------------------------------------------------------------------*/


/*-------------------------------------------关闭一个图形--------------------------------------------*/

void closeOnefigure(Engine* matlabEngine);
/*-----------------------------------------------------------------------------------------------------*/


/*-------------------------------------------关闭所有图形--------------------------------------------*/

void closeAllfigure(Engine* matlabEngine);

/*-----------------------------------------------------------------------------------------------------*/


/*-----------------------------------------MATLAB bar函数-----------------------------------------*/

void Bar(vector<vector<double> >& my_vec2, vector<vector<double> >& compared_vec2, Engine* matlabEngine);

/*-----------------------------------------------------------------------------------------------------*/

Plot.cpp

#include"Plot.h"
#include"GlobalVariable.h"

using std::string;

/*-----------------------------------------MATLAB Plot函数-----------------------------------------*/

void Plot(vector<double>& x_vec, vector<double>& y_vec, string plotCommand, Engine* matlabEngine)
{
	//计算矩阵的列数
	int rowNum = x_vec.size();


	//计算当前编译环境一个double型数据占用几个字节
	double temp = 100;
	int byte = sizeof(temp);


	//定义mxArray数组、赋值、写入MATLAB工作空间
	mxArray *X = mxCreateDoubleMatrix(1, rowNum, mxREAL);
	mxArray *Y = mxCreateDoubleMatrix(1, rowNum, mxREAL);
	memcpy((void *)mxGetPr(X), (void*)(&x_vec.at(0)), rowNum * byte);
	memcpy((void *)mxGetPr(Y), (void*)(&y_vec.at(0)), rowNum * byte);
	engPutVariable(matlabEngine, "X", X);
	engPutVariable(matlabEngine, "Y", Y);


	//向MATLAB引擎发送绘图命令
	engEvalString(matlabEngine, plotCommand.c_str());


	//销毁mxArray数组
	mxDestroyArray(X);
	mxDestroyArray(Y);
}

/*-----------------------------------------------------------------------------------------------------*/


/*----------------------------------------------画资源分配圈-----------------------------------------*/

void CircleCenterPoint(double x, double y, Engine* matlabEngine)
{
	//计算当前编译环境一个double型数据占用几个字节
	double temp = 100;
	int byte = sizeof(temp);


	//定义mxArray数组、赋值、写入MATLAB工作空间
	mxArray *X = mxCreateDoubleMatrix(1, 1, mxREAL);
	mxArray *Y = mxCreateDoubleMatrix(1, 1, mxREAL);
	memcpy((void *)mxGetPr(X), (void*)&x, 1 * byte);
	memcpy((void *)mxGetPr(Y), (void*)&y, 1 * byte);
	engPutVariable(matlabEngine, "X", X);
	engPutVariable(matlabEngine, "Y", Y);


	//资源分配圈画图坐标
	vector<double> circleX_vec;
	vector<double>circleY_vec;
	for (double theta = 0.0; theta <= 2 * PI; theta = theta + PI / 1000.0)
	{
		double x = RS_RADIO*cos(theta);
		double y = RS_RADIO*sin(theta);
		circleX_vec.push_back(x);
		circleY_vec.push_back(y);
	}
	int rowNum = circleX_vec.size();


	//定义mxArray数组、赋值、写入MATLAB工作空间
	mxArray *circleX = mxCreateDoubleMatrix(1, rowNum, mxREAL);
	mxArray *circleY = mxCreateDoubleMatrix(1, rowNum, mxREAL);
	memcpy((void *)mxGetPr(circleX), (void*)(&circleX_vec.at(0)), rowNum * byte);
	memcpy((void *)mxGetPr(circleY), (void*)(&circleY_vec.at(0)), rowNum * byte);
	engPutVariable(matlabEngine, "circleX", circleX);
	engPutVariable(matlabEngine, "circleY", circleY);


	//向MATLAB引擎发送绘图命令
	engEvalString(matlabEngine, "plot(X,Y,'k^')");
	engEvalString(matlabEngine, "plot(circleX,circleY,'k')");


	//销毁mxArray数组
	mxDestroyArray(X);
	mxDestroyArray(Y);
	mxDestroyArray(circleX);
	mxDestroyArray(circleY);
}

/*-----------------------------------------------------------------------------------------------------*/


/*-----------------------------------------画出组内CSBS的R_sa圈------------------------------------*/

void CircleCSBS(vector<CSBS>& GroupCSBS_vec, double R_sa, Engine* matlabEngine)
{
	//计算当前编译环境一个double型数据占用几个字节
	double temp = 100;
	int byte = sizeof(temp);


	for (auto iCSBS = GroupCSBS_vec.begin(); iCSBS != GroupCSBS_vec.end(); iCSBS++)
	{
		//R_sa圈画图坐标
		double x = iCSBS->GetPosition().GetX();
		double y = iCSBS->GetPosition().GetY();
		vector<double> circleX_vec;
		vector<double>circleY_vec;
		for (double theta = 0.0; theta <= 2 * PI; theta = theta + PI / 1000.0)
		{
			double x1 = x + R_sa * cos(theta);
			double y1 =y + R_sa * sin(theta);
			circleX_vec.push_back(x1);
			circleY_vec.push_back(y1);
		}
		int rowNum = circleX_vec.size();


		//定义mxArray数组、赋值、写入MATLAB工作空间
		mxArray *circleX = mxCreateDoubleMatrix(1, rowNum, mxREAL);
		mxArray *circleY = mxCreateDoubleMatrix(1, rowNum, mxREAL);
		memcpy((void *)mxGetPr(circleX), (void*)(&circleX_vec.at(0)), rowNum * byte);
		memcpy((void *)mxGetPr(circleY), (void*)(&circleY_vec.at(0)), rowNum * byte);
		engPutVariable(matlabEngine, "circleX", circleX);
		engPutVariable(matlabEngine, "circleY", circleY);


		//向MATLAB引擎发送绘图命令
		engEvalString(matlabEngine, "plot(circleX,circleY,'r-')");


		//销毁mxArray数组
		mxDestroyArray(circleX);
		mxDestroyArray(circleY);
	}
}

/*-----------------------------------------------------------------------------------------------------*/


/*-------------------------------------------关闭一个图形--------------------------------------------*/

void closeOnefigure(Engine* matlabEngine)
{
	engEvalString(matlabEngine, "close");
}

/*-----------------------------------------------------------------------------------------------------*/


/*-------------------------------------------关闭所有图形--------------------------------------------*/

void closeAllfigure(Engine* matlabEngine)
{
	engEvalString(matlabEngine, "close all");
}

/*-----------------------------------------------------------------------------------------------------*/


/*-----------------------------------------MATLAB bar函数-----------------------------------------*/

void Bar(vector<vector<double> >& my_vec2, vector<vector<double> >& compared_vec2, Engine* matlabEngine)
{
	int lineNum = my_vec2.size();
	int rowNum = my_vec2[0].size();

	//计算当前编译环境一个double型数据占用几个字节
	double temp = 100;
	int byte = sizeof(temp);

	//定义mxArray数组、赋值、
	mxArray *X = mxCreateDoubleMatrix(lineNum, rowNum, mxREAL);
	mxArray *Y = mxCreateDoubleMatrix(lineNum, rowNum, mxREAL);


	//赋值;mxArray数据赋值顺序是一列一列来,而不是一行一行来
	auto ptrX = mxGetPr(X);    //获取指向X实部的指针(指向实部第一个元素)
	auto ptrY = mxGetPr(Y);    //获取指向Y实部的指针(指向实部第一个元素)
	for (int j = 0; j < rowNum; j++)
	{
		for (int i = 0; i < lineNum; i++)
		{
			*ptrX = my_vec2[i][j];
			*ptrY = compared_vec2[i][j];
			ptrX++;
			ptrY++;
		}
	}


	//写入MATLAB工作空间
	engPutVariable(matlabEngine, "X", X);
	engPutVariable(matlabEngine, "Y", Y);


	//向MATLAB引擎发送绘图命令
	string plotCommand = "figure;y_label={'0%','10%','20%','30%','40%','50%','60%','70%','80%','90%','100%'};subplot(1,2,1);bar(X,'stack');title('my');set(gca, 'YTickLabel',y_label);subplot(1,2,2);bar(Y,'stack');title('compared');set(gca, 'YTickLabel',y_label);colormap(bone);legend('资源分配前的子信道','算法分配的子信道','资源分配后仍需要的子信道');";
	engEvalString(matlabEngine, plotCommand.c_str());
}

/*-----------------------------------------------------------------------------------------------------*/

其中,【string plotCommand】就是MATLAB的绘图命令,比如如下调用【Plot】的方法:

Plot(X, SD_ReuseRB, "figure(3);hold on;box on;grid on;xlabel('number of CSBS');ylabel('SD');plot(X,Y,'r-o');", matlabEngine);

猜你喜欢

转载自blog.csdn.net/sinich__eveen/article/details/86557705
今日推荐