QT与matlab混编及完整错误详解

步骤1:   使用matlab生成dll文件,

 选择Library Compiler->C++ SharedLibrary,添加m主文件。

                并将dll文件放入QT相应工程目录文件夹中的debug文件夹中,

                右击QT工程名,添加外部库

                matlab2021a,QT5.9.9。所用c++部件2017

        调用dll的cpp/h文件中添加dll伴生的h头文件

                注:出现error: C2872: “string”: 不明确的符号、error: C2065: “c”: 未声明的标识符

                原因:由于pro文件未正确配置,使得原本无需添加的mclmcrrt.h等MATLAB自带的头文件,需要手动复制到QT工程文件夹中,导致重复定义等问题。

               解决办法:按本文步骤2正确配置pro文件,如果手动将mclmcrrt.h等头文件复制到QT工程文件夹中,会报错。

注:matlab的多个m文件生成dll文件

        使用deploytool时选择主程序的m文件进行生成dll文件,然后在qt调用主程序的function名字,我的例程中,原本主程序是没有function,但是deploytool生成dll出错,做出一些如下修改,

Matlab中的m文件
function TSP()
    ....(内容)
end
QT文件
if (!TSPInitialize()) //DLL 初始化
{
    return; //自行增加
}
TSP();

qt启动后,TSP中调用的其他m文件,后台会自动调用,完美解决困惑...

步骤2:修改pro文件(仅添加如下内容)

TARGET = Matlab  #工程名
TEMPLATE = app

# Matlab 运行库的头文件
INCLUDEPATH += $$quote(D:/Program Files/Polyspace/R2021a/extern/include)   
#目录名称中有空格时才用 $$quote
INCLUDEPATH += $$quote(D:/Program Files/Polyspace/R2021a/extern/include/win64)

win32: LIBS+=-L$$quote(D:/Program Files/Polyspace/R2021a/extern/lib/win64/microsoft) -llibmex
win32: LIBS+=-L$$quote(D:/Program Files/Polyspace/R2021a/extern/lib/win64/microsoft) -llibmx
win32: LIBS+=-L$$quote(D:/Program Files/Polyspace/R2021a/extern/lib/win64/microsoft) -llibmat
win32: LIBS+=-L$$quote(D:/Program Files/Polyspace/R2021a/extern/lib/win64/microsoft)  -llibeng
win32: LIBS+=-L$$quote(D:/Program Files/Polyspace/R2021a/extern/lib/win64/microsoft)  -lmclmcr
win32: LIBS+=-L$$quote(D:/Program Files/Polyspace/R2021a/extern/lib/win64/microsoft)  -lmclmcrrt

#以上路径均为matlab安装文件路径
简化版,容易出问题
DEFINES += __MW_STDINT_H__# microsoft为pro文件所在路径的存放相应文件的文件夹
win32: LIBS+=-L$$PWD/microsoft -llibmex
win32: LIBS+=-L$$PWD/microsoft -llibmx    
win32: LIBS+=-L$$PWD/microsoft -llibmat
win32: LIBS+=-L$$PWD/microsoft  -llibeng
win32: LIBS+=-L$$PWD/microsoft  -lmclmcr
win32: LIBS+=-L$$PWD/microsoft  -lmclmcrrt

注:QT程序运行正常,添加运行dll库初始化语句后报错

Starting D:\01.Notebook\C++\Qt\test\debug\test.exe ...
The program has unexpectedly finished.
The process was ended forcefully.
D:\01.Notebook\C++\Qt\test\debug\test.exe crashed.

pro文件的问题,可能原因一:QT和你“犟”,需要先使用简单函数,走通一遍流程,使得QT与MATLAB之间配置打通,再用复杂程序的dll文件。可能原因二:勿使用简化版的pro文件配置,QT可能找不到。可能原因三:电脑属性中环境变量的系统变量path添加对应路径

D:\Program Files\MATLAB\R2022b\bin\win64
D:\Program Files\MATLAB\R2022b\runtime\win64

步骤3:matlab程序调用

QT中调用的m程序没有返回值,调用格式一般在h头文件的最后

例如

extern LIB_initpop_CPP_API void MW_CALL_CONV initpop(int nargout, mwArray& p, const mwArray& x);

参数1是输出参数个数,此处为1,因此紧跟后面即参数2就是函数的调用结果的接收数组,再后面是输入参数。

void MainWindow::on_pushButton_clicked()
{
    if (!initpopInitialize()) //DLL 初始化
      {
         return; //自行增加
      }
    mwArray num(1,1,mxDOUBLE_CLASS);
    num = ui->lineEdit->text().toDouble();
    mwArray p(1,1,mxDOUBLE_CLASS);
    QByteArray vec;
    mwArray a(1,10,mxDOUBLE_CLASS);
    initpop(1,a,num);
}
m文件:输入参数1个,返回行矩阵

问题1:matlab函数返回值问题

1.1 返回值为常数

本例中,修改initpop函数的函数头为  function  y= initpop();%其中y为常数

extern LIB_initpop_CPP_API void MW_CALL_CONV initpop(int nargout, mwArray& y);

但是mwArray是matlab与C++混编中的数据格式,在QT中输出需要格式转换

若m程序中有一个int返回值,没有输入参数
   mwArray a(1,1,mxDOUBLE_CLASS, mxREAL);//定义数组
    int x;
    initpop(1,a);
    x=(int)a;
    qDebug()<<x;

若m程序中有返回值,有输入参数
initpop(1,a,num); a为返回值,num为输入参数


若m程序中没有返回值,没有输入参数
    TSP();


若m程序中没有返回值,有输入参数  %matlab中无int的数据类型且只满足C语言赋值方法,不满足C++赋值关                
       TSP(a);                 %系,需要是int8
    

1.2 返回值为数组

1.
    QStringList str = {"abc", "qwe", "upo"};
    foreach(QString s , str )
    {
        qDebug()<<s<<" ";
    }
2
mwArray input1(5,2,mxINT8_CLASS);
mwArray input2(5,2,mxINT8_CLASS);
mwArray input1(5,2,mxINT8_CLASS);
    mwArray input2(5,50,mxINT8_CLASS);
    mwArray input3(5,2,mxINT8_CLASS);
    mwArray input4(5,2,mxINT8_CLASS);
    mwArray FC(1,25,mxCELL_CLASS);

    mwArray a(1,1,mxDOUBLE_CLASS);
    mwArray b(1,1,mxDOUBLE_CLASS);//mwArray为调用MATLAB时,参数类型为mwArray
    mwArray mac_num(1,1,mxDOUBLE_CLASS);
    mwArray cost(1,1,mxDOUBLE_CLASS);
    tuple<mwArray,mwArray, mwArray, mwArray> StudIntro=make_tuple(input1,input2,input3,input4); //元胞数组
    FC(1)=input1;

    mac_num=ui->lineEdit->text().toDouble();
    cost=ui->lineEdit_2->text().toDouble();
    Untitled2(4,a,b,input1,input2,mac_num,cost);
    qDebug()<<(int)a;
    qDebug()<<(int)b;
    //我这里的input为返回值,
//mwArray类型矩阵赋值语句是input1.SetData(output1, 4);SetData是output1往input1赋值,即输入
    int output1[10];
    int output2[250];
    input1.GetData(output1,10);  //10代表着矩阵中元素总数,5*2=10
    input2.GetData(output2,250); //GetData是input2往output2里赋值,即输出

    for (int i=0;i<10;i++) {
        qDebug()<<output1[i]<<endl;
    }
    for (int i=0;i<250;i++) {
        qDebug()<<output2[i]<<endl;
    }

1.3 QT接收matlab函数返回值问题

    //输出
    mwArray mac_num(26,1,mxDOUBLE_CLASS);
    mwArray Current_rate(1,1,mxDOUBLE_CLASS);

    current(2,mac_num,Current_rate,material_num1,material_num2,material_num3,material_num4,material_num5,p,t);

    double value = Current_rate.Get(1,1,1);   //三个一的意思分别是一维,第1行,第1列
    qDebug()<<value;
    ui->result_cur->setText(QString::number(value));

问题2:程序异常结束(仅仅是dll库出现问题,与其他无关)

解决办法之一:程序出现问题,若是删除debug文件夹,一定要将dll文件保存,重新构建后再次放入debug文件夹中,不然就会程序异常结束

2.未将dll文件放入debug文件夹

3.多个dll文件,不用时没有彻底删除

        具体做法:删掉build-Login-Desktop_Qt_5_9_9_MSVC2017_64bit-Debug整个文件夹,然后点击构建,执行qmake,按照你自己的dll使用顺序将dll库文件逐个加入到debug文件夹中,每加一个运行一下,总有成功的一次,原因就在于你把你没用的dll库也加入其中,导致错误。

        具体原因是我在调用这三个dll库时,竟然大意的将调用槽函数写成一样,所以就有没有使用dll库而在debug文件夹中加入了dll库文件的离奇错误泪流满面,大意一下浪费一天。

    connect(newActi1 ,SIGNAL(triggered()),this,SLOT(cal_step()));

    connect(newActi2 ,SIGNAL(triggered()),this,SLOT(cal_step()));

    connect(newActi3 ,SIGNAL(triggered()),this,SLOT(cal_step()));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::cal_step()
{
    Current_ *c1 =new Current_();
    this->hide();
    c1->show();

}

void MainWindow::cal2_step()
{
    Max_productivity *max1 =new Max_productivity();
    this->hide();
    max1->show();

}

void MainWindow::cal3_step()
{
    Min_Cost *min1 =new Min_Cost();
    this->hide();
    min1->show();

}

问题3:定义QlineEdit数组,数据的输出

问题4:创建QLineEdit数组,通过QInputDialog输入数据,并显示到QLineEdit,然后应用数据

问题5:Qt:无法解析的外部命令 

1.包含dll运行指令的cpp文件被重置,但依旧在一个工程中,删除debug文件

2.信号对应的槽函数更改后,需要删除整个build文件夹

3.新加入了信号与槽函数

4.未添加外部库,即dll文件

5.删除pro文件的lib注册信息,重新添加外部库

6.工程中的全局变量,static静态成员可以实现(单cpp文件),实例如下:

h文件

namespace Ui {
class Dialog_0;
}

class Dialog_0 : public QDialog
{
    Q_OBJECT

public:
    explicit Dialog_0(QWidget *parent = nullptr);
    ~Dialog_0();
public:
    static QString Process_quantity;   //静态成员变量的定义
    static QString cost_bugdet;

private:
    Ui::Dialog_0 *ui;
};

cpp文件

#include "dialog_0.h"
#include "ui_dialog_0.h"

QString Dialog_0::Process_quantity=0;    //静态成员函数一定要初始化,且初始化程序        
                                         //需要放在任意函数外部
QString Dialog_0::cost_bugdet=0;

Dialog_0::Dialog_0(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog_0)
{
    ui->setupUi(this); 
}

Dialog_0::~Dialog_0()
{
    delete ui;
}


void Dialog_0::on_next_procedure_clicked()
{
    QMessageBox::information(this,"attention","即将输入每道工序详细信息");
    Process_quantity=ui->Edit_macNum->text();
    cost_bugdet=ui->Edit_cost->text();
    qDebug()<<Process_quantity<<" "<<cost_bugdet;

    //Mac_num = Process_quantity;
    //Cost = cost_bugdet;
    Dialog_1 *dia1 =new Dialog_1();
    this->close();
    dia1->show();
}

5.工程中的全局变量,static静态成员可以实现(多cpp文件),实例如下:

传入数据的h文件定义static变量

public:
    static QString start_text;   //静态成员变量的定义
    static QString end_text;

传入数据的cpp文件函数外初始化static变量,函数中传入数据。

QString MapChannel::start_text= " ";   //静态成员变量的定义
QString MapChannel::end_text= " ";
void MapChannel::recvStringSlot(const  QString &text){
    qDebug()<<text;
    start_text = text;
}

其他cpp文件需要数据的只需包含头文件就可直接使用了

MapChannel::start_text   //类名::数据

2.F:\QtCreator\test\zhuchengxu.h:16: error: C1083: 无法打开包括文件: “mclmcrrt.h”: No such file or directory

         Build > Run qmake

问题7:dll生成时,报错:在matlab路径中不能找到该文件(凭记忆翻译的)

在执行deploytool时尽量使MATLAB处于以下路径,即matlab刚启动时的初始路径

MATLAB的工程文件路径中有中文路径,

        预设--工程-修改路径

        预设--工程-日志记录

问题8:QT出现MATLAB is exiting because of fatal error

1.MATLAB的源程序的书写错误,在matlab中无法编译运行,因此也在QT中无法运行

2.QT调用时未传入输入参数

3.QT在使用mwArray定义输入或输出参数后,直接用具体数值定义,未考虑mwArray数据类型与int/string类型之间的转换,就会报这个错,例如:

错误一:    
    mwArray material_num(1,1,mxINT8_CLASS);
    material_num=1000;
错误二:
    mwArray material_num(1,1,mxINT8_CLASS); Int8不等于Int,使用double就好了
    material_num=a.toInt();
    

问题9:mwArray的应用

    int in1[10]={7,27,15,19,20,15,23,13,0,0};
    mwArray input1(5,2,mxINT8_CLASS);
    input1.SetData(in1,10); //in1传入input1

问题10:输入参数是元胞数组时

    int in1[10]={7,27,15,19,20,15,23,13,0,0};
    int in2[10]={4,25,8,22,0, 0,0, 0,0,0};
    int in3[10]={7,40,8,37,9,25,0, 0,0,0};
    int in4[10]={8,16,9,15,10,9,12,6,0,0};
    mwArray input1(5,2,mxINT8_CLASS);
    mwArray input2(5,2,mxINT8_CLASS);
    mwArray input3(5,2,mxINT8_CLASS);
    mwArray input4(5,2,mxINT8_CLASS);

    input1.SetData(in1,10);
    input2.SetData(in2,10);
    input3.SetData(in3,10);
    input4.SetData(in4,10);

    mwArray FC(1,25,mxCELL_CLASS);
    FC(1)=input1;
    FC(2)=input2;
    FC(3)=input3;
    FC(4)=input4;

问题11:QT界面中文显示乱码

1.QString::fromLocal8Bit("对");

2.将乱码所在cpp文件用记事本打开,另存为utf_8格式,替换原有cpp文件

3.pro文件中添加

QMAKE_CXXFLAGS += -execution-charset:utf-8

如果还出错,删除debug文件夹,重新构建。

问题12:QTreeWidgetItem的触发信号问题

问题13:error: C1083: 无法打开包括文件: “mclmcrrt.h”: No such file or directory

        看D:/Program Files/Polyspace/R2021a/extern/include(matlab安装路径中)这个文件夹中是否有该h文件,有的话,刷新一下pro文件的matlab路径设置(删掉在复制一下),或者把最后的/删掉。

问题12:exe打包时matlab程序调用失败

        已经将matlab的dll库文件放在exe所在路径,并修改cpp文件中的文件路径,依旧失败。。。

        QString qstrFileName = QDir::currentPath();
        QString text = QString("/%1.txt").arg(vary_name);
        qstrFileName.append(text);
        QString fileName = qstrFileName;

-L$$PWD/ - - - 表示 .pro所在目录

mclmcrrt9_10.dll不能放在exe所在文件路径下

将microsoft文件夹复制到exe所在文件夹,而删掉的INCLUDEPATH的头文件,需要根据错误提示一一添加。

最终的pro文件里matlab调用库全部代码如下,

win32: LIBS+=-L$$PWD/microsoft -llibmex
win32: LIBS+=-L$$PWD/microsoft -llibmx
win32: LIBS+=-L$$PWD/microsoft -llibmat
win32: LIBS+=-L$$PWD/microsoft  -llibeng
win32: LIBS+=-L$$PWD/microsoft  -lmclmcr
win32: LIBS+=-L$$PWD/microsoft  -lmclmcrrt   

  • 4
    点赞
  • 76
    收藏
    觉得还不错? 一键收藏
  • 15
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值