VS2019+QT5.15.2+matlab联合编程


使用环境

VS2019
QT5.15.2
matlab2022a
建议matlab版本高于vs版本,否则matlab无法使用对应VS版本的编译库

一、如何在将matlab中的函数封装成dll库

在matlab中创建新的脚本文件,并编写自己的需要的函数,比如创建一个两个数相加的函数,function和end中间的是函数部分,c是函数的输出,a和b是函数的输入

function c = mySum(a,b)
	c = a+b;
end	

生成C/C++需要的dll库文件,有两种方式

1、使用mex命令生成

首先在matlab命令行输入!mcc

>> !mcc
Warning: Executing the mcc executable from <matlabroot>/bin/win64 will not be supported in future releases. Execute the mcc command from the <matlabroot>/bin directory or from the MATLAB command window. 
mcc Compile MATLAB functions for deployment outside MATLAB.  
 mcc [-options] fun [fun2...]  
 
Options applicable across all deployment targets:  
 -?  Display help for the mcc command  
 -a  Add additional files or directories to be included in the build  
 -d  Build output directory  
 -g  Include debugging symbol information  
 -I  Add a directory to be searched for MATLAB files  
 -v  Verbose display of build  

如果命令行输出是如图所示,那么编译环境正常,可以进行下一步,输入mex -setup;
如果出现error,那么就是Matlab的编译器不能用,

>> mex -setup
MEX 配置为使用 'Microsoft Visual C++ 2019 (C)' 以进行 C 语言编译。

要选择不同的语言,请从以下选项中选择一种命令:
 mex -setup C++ 
 mex -setup FORTRAN

如果电脑中已经安装VS,那么编译器中会有对应的VS版本编译器,这里选择mex -setup C++,使用C++语言进行编译。

>> mex -setup C++
MEX 配置为使用 'Microsoft Visual C++ 2019' 以进行 C++ 语言编译。

要选择不同的 C++ 编译器,请从以下选项中选择一种命令:
MinGW64 Compiler (C++)  mex -setup:'D:\Program Files\MATLAB\R2022a\bin\win64\mexopts\mingw64_g++.xml' C++
MinGW64 Compiler with Windows 10 SDK or later (C++)  mex -setup:'D:\Program Files\MATLAB\R2022a\bin\win64\mexopts\mingw64_g++_sdk10+.xml' C++
Microsoft Visual C++ 2019  mex -setup:C:\Users\hqy\AppData\Roaming\MathWorks\MATLAB\R2022a\mex_C++_win64.xml C++
>> 

然后选择对应的VS编译器,我这里使用的VS2019,Microsoft Visual C++ 2019,然后输入mbuild -setup

>> mbuild -setup
MBUILD 配置为使用 'Microsoft Visual C++ 2019 (C)' 以进行 C 语言编译。

要选择不同的 C 编译器,请从以下选项中选择一种命令:
MinGW64 Compiler (C)  mex -setup:'D:\Program Files\MATLAB\R2022a\bin\win64\mexopts\mingw64.xml' C -client MBUILD
Microsoft Visual C++ 2019 (C)  mex -setup:C:\Users\hqy\AppData\Roaming\MathWorks\MATLAB\R2022a\MBUILD_C_win64.xml C -client MBUILD

要选择不同的语言,请从以下选项中选择一种命令:
 mex -setup C++ -client MBUILD 
 mex -setup FORTRAN -client MBUILD

选择C++语言进行编译,输入mex -setup C++ client MBUILD,然后选择对应的VS编译器版本。

>>  mex -setup C++ -client MBUILD
MBUILD 配置为使用 'Microsoft Visual C++ 2019' 以进行 C++ 语言编译。

要选择不同的 C++ 编译器,请从以下选项中选择一种命令:
MinGW64 Compiler (C++)  mex -setup:'D:\Program Files\MATLAB\R2022a\bin\win64\mexopts\mingw64_g++.xml' C++ -client MBUILD
MinGW64 Compiler with Windows 10 SDK or later (C++)  mex -setup:'D:\Program Files\MATLAB\R2022a\bin\win64\mexopts\mingw64_g++_sdk10+.xml' C++ -client MBUILD
Microsoft Visual C++ 2019  mex -setup:C:\Users\hqy\AppData\Roaming\MathWorks\MATLAB\R2022a\MBUILD_C++_win64.xml C++ -client MBUILD
>>

环境配置完成之后输入mcc -W cpplib:libmyFunc -T link:lib myFunc.m -C;

-W控制编译之后的封装格式,cpplib表示C++的lib冒号之后是编译输出的lib名字,-T表示目标,link:lib表示连接到lib的目标,mySum表示待编译的文件名,注意输入此命令时,工作路径需要与需要编译的文件一致。

>> mcc -W cpplib:libmySum -T link:lib mySum.m -C
使用 'Microsoft Visual C++ 2019' 编译。 

出现此内容则编译成功,同时函数目录下会出现一系列文件
在这里插入图片描述
其中需要使用的是libmySum.h,libmySum.lib,libmySum.dll,libmySum.ctf,libmySum.def;

2、使用应用程序部署配置

在APP菜单下选择library Compiler
在这里插入图片描述
TYPE选择C++ Shared Libary,然后点击+号,将需要封装的matlab文件添加,最后点击Package。
在这里插入图片描述
如果成功,将会在指定的目录下生成如下文件
在这里插入图片描述
需要使用的内容为mySum/for_redistribution_files_only/目录下的文件

二、在VS中配置matlab环境并调用matlab封装的dll

将封装好的lib文件以及.h文件放在工程目录下。
打开项目的属性页,在VC++目录配置属性>>包含目录,添加matlab安装路径下的include文件路径在这里插入图片描述
在VC++目录配置属性>>库目录下添加matlab安装路径下的microsoft文件路径
在这里插入图片描述
在链接器配置属性>>附加依赖项中添加matlab需要包含的lib文件

libmex.lib
libmx.lib
libmat.lib
libeng.lib
mclmcr.lib
mclmcrrt.lib
xxx.lib //自己封装的lib文件

在这里插入图片描述

三、C/C++类型与matlab类型之间的转换

因为matlab中的类型与C++中的类型存在差异,通常使用mwArray或者mxArray将内容转换为matlab能识别的类型,mxArray:matlab C函数库的结构体;mwArray:matlab C++函数库的关于mxArray的包装类;mwArray的优点在于,该包装类的析构函数能自动销毁对象,不用手动释放内存。

C 数据类型
mxArray	MATLAB数组的C类型
mwSize	mxArray 大小值的 C 类型
mwIndex	mxArray 索引值的 C 类型
mwSignedIndex	mxArray 大小值的有符号整数 C 类型
mxChar	字符串数组的类型
mxLogical	逻辑数组的类型
mxComplexity	指定数组是否具有虚部分量的标志
mxArray属性
mxIsNumeric	确定 mxArray 是否为数值
mxIsComplex	确定数据是否复杂
mxGetNumberOfDimensions	mxArray 中的维数
mxGetElementSize	存储每个数据元素所需的字节数
mxGetDimensions	指向维度数组的指针
mxSetDimensions	修改维度数和每个维度的大小
mxGetNumberOfElements	数值 mxArray 中的元素数
mxCalcSingleSubscript	从第一个元素到所需元素的偏移量
mxGetM	mxArray 中的行数
mxSetM	设置 mxArray 中的行数
mxGetN	mxArray 中的列数
mxSetN	设置 mxArray 中的列数
mxIsEmpty	确定 mxArray 是否为空
mxIsFromGlobalWS	确定mxArray是否是从MATLAB全局工作区复制的

创建阵列常用方法:

mwArray()     创建空的Matlab阵列,类型为mxDOUBLE_CLASS
mwArray(mxClassID mxID)  创建mxID指定类型的Matlab阵列
mwArray(mwSize num_rows,mwSize num_cols,mx_ClassID mxID,mxCompleixity complex=mxREAL) 创建行数为num_rows,列数为num_cols,类型为mxID的Matalb阵列,对于数值型阵列,将complx做为最后一个参数,确定待创建阵列是否为复数阵列

常用mwArray类方法:

setData()		阵列赋值
mwArray Get(mwSize num_indices,....)根据索引返回阵列元素,其中num_indices表示索引数目。Get函数中输入的索引均从1起始。

如何将mwArry中字符串转换成char*类型:

	//mwArry类型转换成char*类型:
	mwArray outLog(logStr);
	mwString ss = outLog.ToString();
	const char* ass = ss.operator const char* ();
	//char* 转换为QString

更多关于mxArray的内容请参阅:
链接: link
更多关于类型转换的内容请参阅
链接: link
更多关于类型转换的内容请参阅
链接: link

四、Qt程序中的matlab函数的调用

在这里插入图片描述
设计如图所示一个界面,实现C=A+B的功能;
QT程序如下:

#include "mySum.h"	//上文通过matlab编译得到的库

blueToothLE_H::blueToothLE_H(QWidget *parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);
    
    connect(ui.doubleSpinBox_A, SIGNAL(valueChanged(double)), this, SLOT(func_Sum()));
    connect(ui.doubleSpinBox_B, SIGNAL(valueChanged(double)), this, SLOT(func_Sum()));
}

blueToothLE_H::~blueToothLE_H()
{
    
}


void blueToothLE_H::func_Sum()
{
	if (!mySumInitialize())							//matlab初始化
	{
		qDebug() << "initial failed";
	}
    double valueA = ui.doubleSpinBox_A->value();	//获取控件数值
    double valueB = ui.doubleSpinBox_B->value();
    mwArray A(1, 1, mxDOUBLE_CLASS);				//定义供matlab函数调用的变量
    mwArray B(1, 1, mxDOUBLE_CLASS);
    mwArray C(1, 1, mxDOUBLE_CLASS);
    A.SetData(&valueA, 1);							//给matlab变量赋值
    B.SetData(&valueB, 1);
    int nargout = 1;								//matlab返回参数数量

    mySum(1, C, A, B);								//调用matlab函数
    //extern LIB_mySum_CPP_API void MW_CALL_CONV mySum(int nargout, mwArray& c, const mwArray& a, const mwArray& b);
    double result = C.Get(1, 1);					//将matlab返回参数转换为C语言类型
    ui.doubleSpinBox_C->setValue(result);
}

注意一定要在使用matlab函数之前调用初始化函数

结果:
在这里插入图片描述

可能遇到的问题:

1、报错帧不在模块中

在这里插入图片描述
打开异常设置中,取消Win32 Exceptions勾选。异常设置在调试>>窗口>>异常设置,或者使用快捷键ctrl+alt+E
在这里插入图片描述

2、程序运行加载过多符号,启动很慢

在属性页面调试配置属性>>调试器类型更改为混合(.NET Core)。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值