欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Visual Studio 编译引擎应用MATLAB 程序

程序员文章站 2022-03-04 14:37:57
...

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?》

https://ww2.mathworks.cn/matlabcentral/answers/467518-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?》

https://ww2.mathworks.cn/matlabcentral/answers/467518-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 如何让环境变量设置后 立即生效》

https://blog.csdn.net/liufangbaishi2014/a

相关标签: MATLAB C VS2017