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
>> Microsoft Visual Stuido Enterprise 2015
>> 密钥

Matlab R2015b win 32位
>> R2015b_win32.iso
>> crack.7z
>> MATLAB_R2015b安装+破解教程.pdf

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运行。

代码用到的头文件自己记得添加,包括「string、vector」等,这里只是主体代码。别忘了最主要的「engine.h」,参看3.1.2。

//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);


未完 ......

点击访问原文(进入后根据右侧标签,快速定位到本文)

C++ 与 MATLAB 混合编程总结(14)的更多相关文章

  1. C++和MATLAB混合编程-DLL

    先小话一下DLL,DLL是动态链接库,是源代码编译后的二进制库文件和程序接口,和静态链接库不同的是,程序在编译时并不链接动态链接库的执行体,而是在文件中保留一个调用标记,在程序运行时才将动态链接库文件 ...

  2. java matlab混合编程之返回值Struct类型

    java matlab混合编程的时候当返回值是Struct类型(matlab中的返回类型)如何来取得(java中)其值? 上网找,看到这个网页:http://www.mathworks.cn/cn/h ...

  3. WPF(C#)与MATLAB混合编程

    WPF(C#)与MATLAB混合编程 WPF可以为开发者提供便捷地构建用户交互界面的解决方法,而matlab则在科学计算方面有着无与伦比的优势,因此在一些需要将科学算法转换为应用软件的项目中,需要应用 ...

  4. VC 与Matlab混合编程之引擎操作详解

    Visual C++ 是当前主流的应用程序开发环境之一,开发环境强大,开发的程序执行速度快.但在科学计算方面函数库显得不够丰富.读取.显示数据图形不方便. Matlab 是一款将数值分析.矩阵计算.信 ...

  5. VS/Qt C++和Matlab混合编程

    最近两天在搞C++和Matlab混合编程,这个中间过程真是让人心酸啊,最后还是搞定成功!现在把这个过程记录一下. 首先自己的电脑本来就安装着matlab2013b,按着网上的说法首先需要输入!mcc, ...

  6. C++和MATLAB混合编程求解多项式系数(矩阵相除)

    摘要:MATLAB对于矩阵处理是非常高效的,而C++对于矩阵操作是非常麻烦的,因而可以采用C++与MATLAB混合编程求解矩阵问题. 主要思路就是,在MATLAB中编写函数脚本并使用C++编译为dll ...

  7. matlab混合编程向导(vc,vb,.net...)

    一.matlab与vc混编  1.通过mcc将matlab的m文件转化为cpp,c文件或dll供vc调用:     这方面的实现推荐精华区Zosco和ljw总结的方法(x-6-1-4-3-1和2)  ...

  8. Matlab混合编程

    Matlab混合编程 混合编程目的 在Matlab中采用混合编程目的主要包括 利用已有的函数库,避免重复工作 加速计算,特别是减少循环所用时间 利用GPU等进行异构编程 混合编程方法-mex函数 目前 ...

  9. C#Matlab混合编程类 初始化问题解决方法

    ************** 异常文本 ************** System.TypeInitializationException: “myPlus.matClass”的类型初始值设定项引发异 ...

随机推荐

  1. archlinux安装nvidia-1050ti闭源驱动教程,亲测

    link:https://blog.csdn.net/u014025444/article/details/91454059

  2. ICEM——倒角的处理

    原视频下载地址: https://pan.baidu.com/s/1miHMOuk 密码: knc4

  3. 13.mysql数据库

    1.mysql数据库建立           yum install mysql-server           mysql -u root                  mysqladmin ...

  4. [C++] typeid关键字使用方法

    typeid 关键字的作用就是获取一个表达式是类型,返回表达式的类型 表达式可以是类型名称.变量名.数字.字符串.指针.结构体等 #include <iostream> using nam ...

  5. 文献阅读 | Benchmarking single cell RNA-sequencing analysis pipelines using mixture control experiments

    资源: sci-hub paper CellBench package - github CellBench_data - code for the paper 现在单细胞领域的突出问题就是工具过多, ...

  6. leetcode 11. Container With Most Water 、42. Trapping Rain Water 、238. Product of Array Except Self 、407. Trapping Rain Water II

    11. Container With Most Water https://www.cnblogs.com/grandyang/p/4455109.html 用双指针向中间滑动,较小的高度就作为当前情 ...

  7. leetcode 384. Shuffle an Array

    384. Shuffle an Array c++ random函数:https://www.jb51.net/article/124108.htm rand()不需要参数,它会返回一个从0到最大随机 ...

  8. JQuery中formSerialize()报错:对象不支持"formSerialize"属性或方法

    formSerialize()是jQuery的表单插件中提供的方法. formSerialize()的核心方法是:$.param(data); Form表单经过formSerialize(),被序列化 ...

  9. Python3基础 print 格式化输出 %% 输出%

             Python : 3.7.3          OS : Ubuntu 18.04.2 LTS         IDE : pycharm-community-2019.1.3    ...

  10. Fiddler抓包工具版面认识(一)

    Fiddler是一个蛮好用的抓包工具,可以将网络传输发送与接受的数据包进行截获.重发.编辑.转存等操作.也可以用来检测网络安全.反正好处多多,举之不尽呀!当年学习的时候也蛮费劲,一些蛮实用隐藏的小功能 ...