Visual Studio 编译引擎应用MATLAB 程序
1.问题描述
控制算法仿真测试过程中需要同时使用Visual Studio 和MATLAB 软件,Visual Studio编写Code C,MATLAB用做数据分析。经常遇到编译完一个软件还要打开另一个软件的问题。因此想到使用Visual Studio 直接配置使用MATLAB。
2.软件版本
Visual Studio 17
MATLAB R2018b
3.使用MATLAB提供的库
3.1 说明
1.MATLAB提供了使用demo,位于matlabroot\extern\examples\eng_mat\ [matlabroot:MATLAB安装目录],可作为基本使用参考代码;
e.g: file://engdemo.c
/*
* engdemo.c
*
* A simple program to illustrate how to call MATLAB
* Engine functions from a C program.
*
* Copyright 1984-2016 The MathWorks, Inc.
* All rights reserved
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "engine.h"
#define BUFSIZE 256
int main()
{
Engine *ep;
mxArray *T = NULL, *result = NULL;
char buffer[BUFSIZE+1];
double time[10] = { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0 };
/*
* Call engOpen with a NULL string. This starts a MATLAB process
* on the current host using the command "matlab".
*/
if (!(ep = engOpen(""))) {
fprintf(stderr, "\nCan't start MATLAB engine\n");
return EXIT_FAILURE;
}
/*
* PART I
*
* For the first half of this demonstration, send data
* to MATLAB, analyze the data, and plot the result.
*/
/*
* Create a variable for the data
*/
T = mxCreateDoubleMatrix(1, 10, mxREAL);
memcpy((void *)mxGetPr(T), (void *)time, sizeof(time));
/*
* Place the variable T into the MATLAB workspace
*/
engPutVariable(ep, "T", T);
/*
* Evaluate a function of time, distance = (1/2)g.*t.^2
* (g is the acceleration due to gravity)
*/
engEvalString(ep, "D = .5.*(-9.8).*T.^2;");
/*
* Plot the result
*/
engEvalString(ep, "plot(T,D);");
engEvalString(ep, "title('Position vs. Time for a falling object');");
engEvalString(ep, "xlabel('Time (seconds)');");
engEvalString(ep, "ylabel('Position (meters)');");
/*
* use fgetc() to pause long enough to be
* able to see the plot
*/
printf("Hit return to continue\n\n");
fgetc(stdin);
/*
* We're done for Part I! Free memory, close MATLAB figure.
*/
printf("Done for Part I.\n");
mxDestroyArray(T);
engEvalString(ep, "close;");
/*
* PART II
*
* For the second half of this demonstration, we will request
* a MATLAB string, which should define a variable X. MATLAB
* will evaluate the string and create the variable. We
* will then recover the variable, and determine its type.
*/
/*
* Use engOutputBuffer to capture MATLAB output, so we can
* echo it back. Ensure first that the buffer is always NULL
* terminated.
*/
buffer[BUFSIZE] = '\0';
engOutputBuffer(ep, buffer, BUFSIZE);
while (result == NULL) {
char str[BUFSIZE+1];
char *input = NULL;
/*
* Get a string input from the user
*/
printf("Enter a MATLAB command to evaluate. This command should\n");
printf("create a variable X. This program will then determine\n");
printf("what kind of variable you created.\n");
printf("For example: X = 1:5\n");
printf(">> ");
input = fgets(str, BUFSIZE, stdin);
/*
* Evaluate input with engEvalString
*/
engEvalString(ep, str);
/*
* Echo the output from the command.
*/
printf("%s", buffer);
/*
* Get result of computation
*/
printf("\nRetrieving X...\n");
if ((result = engGetVariable(ep,"X")) == NULL)
printf("Oops! You didn't create a variable X.\n\n");
else {
printf("X is class %s\t\n", mxGetClassName(result));
}
}
/*
* We're done! Free memory, close MATLAB engine and exit.
*/
printf("Done!\n");
mxDestroyArray(result);
engClose(ep);
return EXIT_SUCCESS;
}
2.配置过程中主要遇到如下两个问题:
(1).LINK2019错误;
(2).程序无法启动,缺少libmx.dll库;
3.2 LINK2019错误
问题现象:
错误 LNK2019 无法解析的外部符号 engOpen,该符号在函数 "int __cdecl MatlabEngine(void)" ([email protected]@YAHXZ) 中被引用 MatEngine D:\Coder\MatEngine\MatEngine\stdafx.obj 1
错误 LNK2019 无法解析的外部符号 mxDestroyArray_800,该符号在函数 "int __cdecl MatlabEngine(void)" ([email protected]@YAHXZ) 中被引用 MatEngine D:\Coder\MatEngine\MatEngine\stdafx.obj 1
错误 LNK2019 无法解析的外部符号 engClose,该符号在函数 "int __cdecl MatlabEngine(void)" ([email protected]@YAHXZ) 中被引用 MatEngine D:\Coder\MatEngine\MatEngine\stdafx.obj 1
原因分析:
编译链接过程中,缺少MATLAB第三方静态库*.lib
解决方式:
具体的配置过程参照:[2].《How can I build a C++ program using MATLAB Engine in Visual Studio?》
设置项目静态依赖库(*.lib)的时候,教程中间只调用了libMatlabEngine.lib;libMatlabDataArray.lib没有调用以下【引擎库 - matlabroot/extern/lib/win64/microsoft/libeng.lib】和【MATLAB 矩阵库 - matlabroot/extern/lib/win64/microsoft/libmx.lib】需要把这两个库加上。
具体描述如下:
您需要 libeng 和 libmx 共享库。文件的名称是特定于平台的。将这些库名称添加到您的 IDE 配置中。有关说明,请参阅您的 IDE 产品文档。
Windows 库
Microsoft
引擎库 - matlabroot/extern/lib/win64/microsoft/libeng.lib
MATLAB 矩阵库 - matlabroot/extern/lib/win64/microsoft/libmx.lib
MinGW
引擎库 - matlabroot/extern/lib/win64/mingw64/libeng.lib
MATLAB 矩阵库 - matlabroot/extern/lib/win64/mingw64/libmx.lib
Linux 库
引擎库 - matlabroot/extern/bin/glnxa64/libeng.so
MATLAB 矩阵库 - matlabroot/extern/bin/glnxa64/libmx.so
macOS 库
引擎库 - matlabroot/extern/bin/maci64/libeng.dylib
MATLAB 矩阵库 - matlabroot/extern/bin/maci64/libmx.dylib
3.3 程序无法启动,缺少libmx.dll库
现象描述:
程序无法启动,缺少libmx.dll。
原因分析:
matlab2018b版本的环境变量导致;libmx.dll是存在于matlabroot/MATLAB/R2018b/bin/win64文件夹中。
解决方式:
把matlabroot/MATLAB/R2018b/bin/win64添加到环境变量即可。
PS: 关于关于环境变量[7] [8]
4.使用BAT不显示GUI执行MATLAB脚本
(1)matlab-operator.bat
matlab -nosplash -nodesktop -r "run H:\...\Draw_R1.m" -sd "H:\..."
(2)main.cpp
void main()
{
system("start matlab-operator.bat ");
system("pause");
}
解释:运行main.cpp通过system函数调用matlab-operator.bat脚本,matlab-operator以matlab支持的方式运行matlab,其本质是通过DOS启动matlab并运行指定脚本Draw_R1.m
3、4中两种方式的效果基本一致;
5.附录
附加包含目录:
C:\Program Files\MATLAB\R2018b\extern\include
库目录:
C:\Program Files\MATLAB\R2018b\extern\lib\win64\microsoft
C:\Program Files\MATLAB\R2018b\extern\lib\win64\mingw64
C:\Program Files\MATLAB\R2018b\extern\bin\win64
C:\Program Files\MATLAB\R2018b\bin\win64\libmx.dll
库:
libMatlabEngine.lib;libMatlabDataArray.lib;
libeng.lib;libmx.lib;
调试环境:
PATH=C:\Program Files\MATLAB\R2018b\extern\bin\win64;%PATH%
C:\Program Files\MATLAB\R2018b\bin\win64
Reference:
[1].《使用 IDE 编译引擎应用程序》https://ww2.mathworks.cn/help/matlab/matlab_external/compiling-engine-applications-in-an-ide.html
[2].《How can I build a C++ program using MATLAB Engine in Visual Studio?》
[3] 《error LNK2019: 无法解析的外部符号》
https://blog.csdn.net/maizousidemao/article/details/81452279
[4] “error LNK2019: 无法解析的外部符号”的几种可能原因
https://blog.csdn.net/shenziheng1/article/details/54588457#commentBox
[5] 《计算机中丢失libmx.dll 错误解决》
https://www.geek-share.com/detail/2597388862.html
[6] 《windows用户变量和系统变量的区别》
https://blog.csdn.net/sxhlovehmm/article/details/44274633
[7] 《Windows 如何让环境变量设置后 立即生效》
推荐阅读
-
使用Visual Studio2019创建C#项目(窗体应用程序、控制台应用程序、Web应用程序)
-
【转载】Visual Studio2017如何设置打包发布的WinForm应用程序的版本号
-
使用 Visual Studio 2022 开发 Linux C++ 应用程序的过程详解
-
Visual Studio 2017 - Windows应用程序打包成exe文件(1)- 工具简单总结
-
通过Windows Visual Studio远程调试WSL2中的.NET Core Linux应用程序的方法
-
visual studio 2012 C/C++程序的创建、编辑、编译和运行过程
-
剖析并利用Visual Studio Code在Mac上编译、调试c#程序
-
(Windows)Visual Studio code创建gradle应用程序
-
使用Visual Studio Code开发(编译、调试)C++程序与Java程序
-
使用Visual Studio2019创建C#项目(窗体应用程序、控制台应用程序、Web应用程序)