Detailed explanation of the use of mwArray array in Qt and Matlab mixed programming

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

  1. 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
}
  1. 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);

Tags: MATLAB security Data Mining Network Protocol

Posted on Wed, 01 Dec 2021 11:06:46 -0500 by Cannibal_Monkey