- 在实际项目中,为了更快的验证不同算法的性能优劣,由于matlab独特的优势(矩阵运算,弱类型,可视化等等),我们通常会先使用matlab验证。
- 验证完成之后,由于实时性问题,通常需要我们转成c,c++,java等语言用于实际工程项目中。目前matlab转c或者c++大致有三种方式:
1.通过第三方库如eigen,原生态转成c++
2.通过matlab coder将matlab文件直接转成c++
3.通过matlab compiler将matlab函数打包成.h和动态链接库,在c++调用。 - 以上三种方式的实时性,理论上第一种方式实时性最高,第三种方式最低,第二种其次。但是在开发的周期和效率方面,则相反,第一种方式开发周期最长,第三种最短。
- 如果对实时要求较高,建议使用第一种方式,如果对实时性要求不高(比如离线数据处理等),建议使用第三种方式。
- 本文主要讲述在linux环境下如何使用第三种方式:通过matlab compiler将matlab函数打包成.h和动态链接库,在c++调用。
下面我们开始
- 第一步:下载matlab。下载好linux下的matlab,随便哪个版本都OK,建议下载较新的,2018a 或者 2017b。
- 第二步:确定gcc/g++的版本。确定好自己linux版本的gcc/g++版本,输入命令
gcc -v
和g++ -v
查看 ,然后再确定matlab版本所支持的gcc版本,根据自己已安装的matlab版本,自行下载查看。尽量保证matlab gcc 版本和 linux的gcc版本一致,至少不能低于所要求的版本!如果版本不一致或者有系统有多个版本,请参照这里和这里。如果出现以下错误请参照这里.:
Err http://archive.ubuntu.com yakkety/main amd64 Packages 404 Not Found
-
第三步:确定QT版本。进入Matlab安装目录,运行命令
sudo find . -name libQt*
,通过动态链接库查看当前matlab所支持的最高QT版本。如果出现的都是libQtxxx.so.5.5.x
,说明matlab所支持的最高QT版本为QT5.5,QT下载地址,如果已经下载了qtcreat,那么请先选择版本后然后进入single
下载,然后按照这里操作,安装成功之后将新的QT版本路径加载到QTcreate中去即可,并在项目中切换即可。
image.png
image.png
image.png 第四步:编写一个简单的matlab程序,
aaa.m
文件:
function [hello] = aaa(dir_name)
hello = dir_name;
end
-
然后在command window输入:
deploytool
选择LIbrary Compiler
,如下图所示:
image.png -
进入
Matlab Compiler
界面,选择c++ share Library
,再点击+
,选择aaa.m
文件
image.png
image.png -
然后再点击
package
打包,设置prj文件的路径之后,就会出现如下图所示的界面。
image.png -
如果出现以下界面说明打包成功,注意:如果
gcc
版本不一致会给出警告,可以点击logfile
文件查看信息,另外由于动态链接库的必须使用lib开头(正常应该是libaaa.so
),这里是(aaa.so
),所以也会给出警告。后续导入到QT pro进去之前需要将aaa.so
重命名为libaaa.so
.
image.png -
进入打包好的文件夹,如下图
image.png
我们只要for_redistribution_files_only
目录下面的.h .so
文件即可。记得把aaa.so
重命名为libaaa.so
-
第五步:在QT create中调用c++。打开qtcreate新建一个application应用.
image.png - 在pro文件中添加打包
aaa.h
头文件和libaaa.so
文件路径,另外,我们还需要加一个matlab的动态库:libmwmclmcrrt.so
,以及头文件mclmcrrt.h
和mclcppclass.h
。
MainWindow.cpp
代码如下:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include<QLabel>
#include"aaa.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
char temp_dirpath[150] = "hello world";
if(!aaaInitialize())
{
std::cout<<" init error"<<std::endl;
}
mwArray mydirpath(temp_dirpath),hello;
aaa(1,hello,mydirpath);
char str[50];
strcat(str, hello.ToString());
QLabel *test = new QLabel(this);
test->setText(QString(str));
}
MainWindow::~MainWindow()
{
delete ui;
}
.pro
文件如下:
#-------------------------------------------------
#
# Project created by QtCreator 2019-01-21T10:34:33
#
#-------------------------------------------------
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = matlabtest
TEMPLATE = app
# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
mainwindow.cpp
HEADERS += \
mainwindow.h
FORMS += \
mainwindow.ui
INCLUDEPATH += /home/simin/matlabPro/aaa/for_redistribution_files_only \
/usr/local/MATLAB/MATLAB_Runtime/v93/extern/include/
LIBS += \
-L/home/simin/matlabPro/function_test/for_redistribution_files_only \
-L/home/simin/matlabPro/aaa/for_redistribution_files_only \
-L/usr/local/MATLAB/MATLAB_Runtime/v93/runtime/glnxa64 \
-lmwmclmcrrt -laaa
编译运行结果:
- 说明:aaaInitialize为aaa.h matlab提供的初始化函数(必须)。aaa.h文件里面看这两个函数
bool MW_CALL_CONV aaaInitialize(void);
extern LIB_aaa_CPP_API void MW_CALL_CONV aaa(int nargout, mwArray& hello, const mwArray& dir_name);
其中int nargout
为输出参数的个数。
如果是转C语言,只需在第四步
打包的时候选择C share library
,然后将MainWindow.cpp
对应的部分修改下面所示即可。
/**C**/
if(!aaaInitialize())
{
std::cout<<"init error"<<std::endl;
}
mxArray *mychar = mxCreateString(temp_dirpath);
mlfAaa(mychar);
aaaTerminate();
aaaPrintStackTrace();
mclTerminateApplication();
/**C**/
主要问题汇集:
- 程序打包过程中出错:查看logfile文件的错误信息,大部分是gcc编译器的问题。
- 使用qtcreate 运行程序出现:xxxxx/glnxa64/libmat.so: shared object not open
QT版本高于matlab版本所要求的QT版本所导致。解决办法请看第三步
。 - 如提示需要安装MCR,则在matlab 命令行中输入
mcrinstaller
,如有则会给出安装包的路径mcrinstaller.zip
,根据路径解压之后,进入目录执行./install
即可。