Original link: https://blog.csdn.net/HongAndYi/article/details/79477031
content validity
In the basic flow of Qt 5.9 and matlab 2017b mixed programming, the basic flow of MATLAB and C + + mixed programming is introduced. After the flow is through, the key is to realize the function through the function in DLL.
The function compiled by MATLAB has a unified interface form of input and output parameters, mainly using mwArray type array. In the previous blog post, there was no detailed introduction to mwArray. There are still some detailed problems in actual use. In this article, we will introduce the use of mwArray in detail.
The main contents include:
(1) mwArray array creation, setting real data
(2) Main functions and methods of mwArray
(3) Pass complex data to mwArray array
(4) Pass string data to mwArray array
Qt 5.9 test project operation interface is shown in the figure below, and the tools and environments used are:
matlab 2017b
Qt 5.9
MSVC 2015 64 bit compiler
Windows 7 64 bit
- Prepare the m file and compile the generated DLL
Write three m function files in Matlab
function C= matAdd(A,B) % C= matAdd(A,B), Addition of two matrices C=A+B; end function [C]= matAbs(A) % Find the absolute value or modulus of each element of the matrix, if A For the complex matrix, find the modulus of each element C=abs(A); end function [C]= matLoadDataFile(filename) % Load array from a file C=load(filename); end
Note that these three functions need to be saved as m files.
Use deploytool to start MATLAB Compiler, add these three m files and compile them into C++ Shared Library. The compiled project is saved as matBasics.prj, and the compiled \ for_ redistribution_ files_ The files in the only directory are shown in the following figure
2. matBasics.dll is used in QT project
2.1 Qt project creation and. pro file setting
Create a Qt Widget Application in Qt Creator. The project name is test1. The main window is based on QMainWindow. Create a \ include directory under the file directory of the project and copy the matBasics.h and matBasics.lib files to this directory.
Import the library file matBasics.lib through Add Library, and add Matlab related library files and header file search paths. Let MATLAB 2017b be installed in D:\MATLAB 2017b directory, and the test1.pro file after setting is as follows:
QT += core gui greaterThan(QT_MAJOR_VERSION, 4): QT += widgets TARGET = test1 TEMPLATE = app DEFINES += QT_DEPRECATED_WARNINGS SOURCES += \ main.cpp \ MainWindow.cpp \ HEADERS += \ MainWindow.h \ include/matBasics.h \ FORMS += \ MainWindow.ui #User defined DLL library of MATLAB program win32: LIBS += -L$$PWD/include/ -lmatBasics INCLUDEPATH += $$PWD/include DEPENDPATH += $$PWD/include # Header file of Matlab runtime # . h file search path INCLUDEPATH += D:/MATLAB2017b/extern/include INCLUDEPATH += D:/MATLAB2017b/extern/include/Win64 # MATLAB. lib library file used INCLUDEPATH += D:/MATLAB2017b/extern/lib/win64/microsoft DEPENDPATH += D:/MATLAB2017b/extern/lib/win64/microsoft win32: LIBS += -LD:/MATLAB2017b/extern/lib/win64/microsoft/ -llibmex win32: LIBS += -LD:/MATLAB2017b/extern/lib/win64/microsoft/ -llibmx win32: LIBS += -LD:/MATLAB2017b/extern/lib/win64/microsoft/ -llibmat win32: LIBS += -LD:/MATLAB2017b/extern/lib/win64/microsoft/ -llibeng win32: LIBS += -LD:/MATLAB2017b/extern/lib/win64/microsoft/ -lmclmcr win32: LIBS += -LD:/MATLAB2017b/extern/lib/win64/microsoft/ -lmclmcrrt
2.2 initialization of matbasics.dll
Before using the function in matBasics.dll, you need to call the function matBasicsInitialize() in matBasics.h to initialize. We will complete the initialization in the constructor of the window. Here is the code for the constructor:
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); if (matBasicsInitialize()) //Initialization must be called ui->plainTextEdit->appendPlainText("matlab program DLL Initialization succeeded."); else { ui->plainTextEdit->appendPlainText("*** matlab program DLL initialization failed"); return; } qsrand(QTime::currentTime().msec()); //Initialize random number seed }
- Use of mwArray class
3.1 common constructors for mwarray class variables
The common constructors of mwArray class are as follows:
mwArray(mwSizenum_rows,mwSizenum_cols,mxClassIDmxID,mxComplexitycmplx=mxREAL)
num_rows represents the number of rows and mwSize is an integer type
num_cols indicates the number of columns
mxID is an mxClassID type, which represents the basic data type of an element. Common values are as follows
mxLOGICAL_CLASS, mxCHAR_CLASS, mxDOUBLE_CLASS, mxSINGLE_CLASS, mxINT8_CLASS, mxUINT8_CLASS, mxINT16_CLASS, mxUINT16_CLASS, mxINT32_CLASS, mxUINT32_CLASS, mxINT64_CLASS, mxUINT64_CLASS,
cmplx is of type mxComplexity and has two values: mxREAL and mxCOMPLEX. The bid array element is real or complex, and the default is mxREAL
3.2 definition and assignment of mwarray class variables and significance of common functions
The response code of the "parameters of matrix A" button on the window is as follows:
void MainWindow::on_btnParams_clicked() {// Find various parameters of matrix A, that is, the function of the main function of mwArray class int rowCntA=ui->spinBoxA_Row->value();//Number of rows int colCntA=ui->spinBoxA_Col->value();//Number of columns //Read matrix A int elementCntA=rowCntA*colCntA;//Number of elements double *arrayA=new double[elementCntA]; //One dimensional array int N=0;//Element index number of one-dimensional array for(int i=0;i<ui->tableA->columnCount();i++) //Read column by column and store by column for (int j=0; j<ui->tableA->rowCount();j++) { arrayA[N]=ui->tableA->item(j,i)->text().toDouble(); N++; } mwArray matrixA(rowCntA,colCntA,mxDOUBLE_CLASS, mxREAL);//Define array matrixA.SetData(arrayA,elementCntA); //Set data // Significance of main functions of mwArray class ui->plainTextEdit->clear(); mwSize dims=matrixA.NumberOfDimensions(); //Dimension of matrix, scalar, value 1 = one-dimensional sequence, 2 = two-dimensional array ui->plainTextEdit->appendPlainText(tr("mwArray::NumberOfDimensions() Dimension of matrix, scalar")); ui->plainTextEdit->appendPlainText(tr(" 1 Represents a one-dimensional matrix and 2 represents a two-dimensional matrix")); ui->plainTextEdit->appendPlainText(tr(" matrixA.NumberOfDimensions()=%1").arg(dims)); mwArray arrayDim=matrixA.GetDimensions();//Is a one-dimensional array, number of elements = NumberOfDimensions() ui->plainTextEdit->appendPlainText(tr("\n mwArray::GetDimensions()Is the specific size of the matrix, that is, the number of rows and columns")); ui->plainTextEdit->appendPlainText(" matrixA.GetDimensions()Results:"); for(int i=1;i<=dims;i++) { int cnt=arrayDim.Get(dims,i);//Even if dims=2, i represents the element index, which is feasible // int cnt=arrayDim.Get(1,i); // One dimensional vector ui->plainTextEdit->appendPlainText(tr(" The first%1 Dimension size = %2").arg(i).arg(cnt)); } mwSize elementCnt=matrixA.NumberOfElements();//Number of elements ui->plainTextEdit->appendPlainText(tr("\n mwArray::NumberOfElements() Number of elements=Number of rows*Number of columns")); ui->plainTextEdit->appendPlainText(tr(" matrixA.NumberOfElements()=%1").arg(elementCnt)); }
Here, we need to pay attention to the following issues:
(1) Assignment of mwArray array
mwArray:: SetData(mxUint64* buffer, mwSizelen) is used to assign values to the array
Among them, buffer must be a one-dimensional array. Even if mwArray variable is a two-dimensional array, len is the number of elements of one-dimensional array, which is equal to the number of rows multiplied by the number of columns. When assigning a value to a two-dimensional array, the buffer must store data by column (see code content)
(2) The mwSize mwArray::NumberOfDimensions() function returns an integer scalar representing the dimension of the array
The return value is 1 for one-dimensional array and 2 for two-dimensional array.
The program test returns 2 in all cases, even if it is a row vector or column vector.
(3) Mwarray mwarray:: getdimensions() returns an array representing the size of each dimension of the array. For a vector or two-dimensional array, the return value is two elements. The first element represents the number of rows and the second element represents the number of columns.
(4) mwSize mwArray::NumberOfElements() returns the number of elements of the array, which is equal to the number of rows multiplied by the number of columns
(5) Other common functions of mwArray
The return value of bool IsComplex() const indicates whether the array is a complex type
The return value of bool IsEmpty() const indicates whether the array is empty
The return value of bool IsNumeric() const indicates whether the matrix is numeric
Parameters of an array with 1 row and 1 column
Parameters of an array of 1 row and 4 columns
Parameters of an array of 3 rows and 1 column
3.3 reading of mwarray array data
The response code of the "C=A" button on the interface is as follows. Its function is to directly copy array A to array C and read out the contents of C for display.
void MainWindow::on_btnAssign_clicked() {//C=A, assignment with operator int rowCnt=ui->spinBoxA_Row->value(); int colCnt=ui->spinBoxA_Col->value(); int elementCnt=rowCnt*colCnt;//Number of elements mwArray matrixA(rowCnt,colCnt,mxDOUBLE_CLASS, mxREAL);//Define array, 2 rows, 3 columns, double type //Read array A, double *arrayA; arrayA=new double[elementCnt]; int N=0; for(int i=0;i<ui->tableA->columnCount();i++) for (int j=0; j<ui->tableA->rowCount();j++) { // matrixA(j,i)=ui->tableA->item(j,i)->text().toDouble(); // You cannot assign this value arrayA[N]=ui->tableA->item(j,i)->text().toDouble(); N++; } matrixA.SetData(arrayA,elementCnt); //Read results // mwArray matrixC(rowCnt,colCnt,mxDOUBLE_CLASS, mxREAL);// Define array, 2 rows, 3 columns, double type mwArray matrixC=matrixA; ui->spinBoxC_Row->setValue(rowCnt); ui->spinBoxC_Col->setValue(colCnt); int dim=2; //Array dimension, representing a two-dimensional array N=1; for(int i=1; i<=colCnt;i++) for(int j=1; j<=rowCnt;j++) { // double value=matrixC(j,i); // Index directly with array subscript, row J, column I // double value=matrixC(N); // Read directly by element sequence number, the nth element // double value=matrixA.Get(dim,j,i); // Read out according to the dim dimension array to obtain the data of row J and column I double value=matrixA.Get(dim,N); //Read out according to the dim dimension array and read the elements with sequence number N N++; QTableWidgetItem *item=new QTableWidgetItem(QString::asprintf("%.0f",value)); item->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter); ui->tableC->setItem(j-1,i-1,item); } }
This code should pay attention to the following problems:
(1) matrixA uses the SetData() function to assign values
mwArray matrixA(rowCnt,colCnt,mxDOUBLE_CLASS, mxREAL); matrixA.SetData(arrayA,elementCnt);