VS calls Matlab Engine method
Friends who are interested in trajectory planning or c/matlab hybrid programming can pay attention to the two parts of the OTPL open source project code: https://github.com/libing403/OTPL and https://github.com/libing403/OTPL/tree /master/OTPL/TestDemo/MatlabEngineCode
The project is mainly developed on the basis of the theory of the following two books:
Trajectory Planning for Automatic Machines and Robots;
The NURBS Book
Matlab mainly faces the high-tech computing environment of scientific computing, visualization and interactive programming, but because the programs developed on the Matlab development platform cannot be separated from the Matlab operating environment, it is not flexible enough to deal with some practical application problems, while VC++ To a certain extent, it can make up for this deficiency. The c language is not convenient for data visualization, making it difficult to test and analyze the results of some programs that must be implemented in c language. Therefore, combining the two and sharing their strengths can provide more powerful technical support for scientific research and engineering development.
Configure VS project properties
The environment I am using is
x86
Windows 7
VS2015
MATLAB R2016a (other versions are similar)
Make the following settings in the built VS project
1. Configuration Properties -> VC++ Directories -> Include Directories
Edited to: under the Matlab installation path...\extern\include;
2. Configuration properties -> VC++ directory -> library directory
Edited to: under the Matlab installation path...\extern\lib;
3. Configuration Properties -> Linker -> Input -> Additional Dependencies
Add: libeng.lib;libmx.lib;libmex.lib;libmat.lib (add the lib needed in the program here)
system environment variables
Add D:\MatLab\R2010a\bin\win64; to PATH to help VS find the dynamic link library provided by MATLAB.
Register MATLAB server : cmd, run in D:\MatLab\R2010a\bin directory
matlab \regserver
Sometimes it is registered during installation, and this command does not work.
Call matlab engine in VS
include header files
#include "engine.h"
Turn on the engine
Engine* pEng = NULL;
if (!(pEng = engOpen(NULL)))
{
printf("Open matlab enging fail!");
getchar();
return -1;
}
Common functions for setting/getting data to matlab workspace
int engPutVariable(Engine *ep, const char *name, const mxArray *pm)
Set the value of a variable array
mxArray *engGetVariable(Engine *ep, const char *name) gets a variable
int engEvalString(Engine* ep, const char* string) executes Matlab expression
shut down the engine
if(pEng)
engClose(pEng);
Example
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<engine.h>
#define dataNum 100
int main()
{
int ret = 0;
Engine* eg = NULL;
if (!(eg = engOpen(NULL)))
{
printf("Open matlab enging fail!");
return 1;
}
double xtemp[dataNum] = { 0 };
double ytemp[dataNum] = { 0 };
for (int i = 0; i < dataNum; i++)
{
xtemp[i] = i * 2.0 * 3.1415926 / 100.0;
ytemp[i] = sin(xtemp[i]);
}
mxArray *X = mxCreateDoubleMatrix(1, dataNum, mxREAL);//创建matlab存储数据的指针
mxArray *Y = mxCreateDoubleMatrix(1, dataNum, mxREAL);
memcpy(mxGetPr(X), xtemp, dataNum * sizeof(double)); //数据复制
memcpy(mxGetPr(Y), ytemp, dataNum * sizeof(double));
if ((ret = engPutVariable(eg, "X", X)) != 0) //把数据传递到matlab工作空间,并命名为X
printf("engPutVariable error:%d\n", ret);
if ((ret = engPutVariable(eg, "Y", Y)) != 0)
printf("engPutVariable error:%d\n", ret);
engEvalString(eg, "plot(X,Y)");//运行绘图命令
getchar();
if(eg)
engClose(eg);
return 0;
}
The result of running the example is as follows
Write matlab command wrapper function
It can be seen from the above programming that calling matlab for drawing is also cumbersome, such as creating variables, copying memory data, running command expressions and a series of operations. In order to invoke the experience of running matlab commands like in matlab, you can encapsulate matlab commands into functions in C language. For example, the following is a wrapper around the plot command:
int mat_plot(Engine *eg, double *x, double *y, int N, char *LineStyle, double LineWidth, double MarkerSize)
{
int ret = 0;
mxArray *X = mxCreateDoubleMatrix(1, N, mxREAL);
mxArray *Y = mxCreateDoubleMatrix(1, N, mxREAL);
mxArray *MS = mxCreateDoubleScalar(MarkerSize);
memcpy(mxGetPr(X), x, N * sizeof(double));
memcpy(mxGetPr(Y), y, N * sizeof(double));
if ((ret = engPutVariable(eg, "X", X)) != 0)
printf("engPutVariable error:%d\n", ret);
if ((ret = engPutVariable(eg, "Y", Y)) != 0)
printf("engPutVariable error:%d\n", ret);
//gennerate the plot command
char plotCommand[256] = "fig=plot(X,Y,'";
//set line style and marker
if (strlen(LineStyle) > 0)
strncat(plotCommand, LineStyle, strlen(LineStyle));
else
{
strncat(plotCommand, "-", strlen("-"));
}
strncat(plotCommand, "',", strlen(LineStyle));
char temp[20] = "";
//set line width
if (LineWidth < 1.0)
LineWidth = 1.0;
strncat(plotCommand, "'LineWidth',", strlen("'LineWidth',"));
memset(temp, 0, sizeof(temp));
sprintf(temp, "%f,", LineWidth);
strncat(plotCommand, temp, strlen(temp));
//set marker size
strncat(plotCommand, "'MarkerSize',", strlen("'MarkerSize',"));
sprintf(temp, "%f", MarkerSize);
strncat(plotCommand, temp, strlen(temp));
strncat(plotCommand, ");", strlen(temp));
//plot
if ((ret = engEvalString(eg, plotCommand)) != 0)
{
printf("\nplot Command error:%s\n", plotCommand);
return ret;
}
engEvalString(eg, "set(gcf,'color','w');");
printf("plot Command ok:%s\n", plotCommand);
//destroy mxArray,but they are still in matlab workspace
mxDestroyArray(X);
mxDestroyArray(Y);
return 0;
}
In this way, it is much more convenient to use the matlab command. For example, I want to use the data calculated in the C language to draw a picture, and I can directly call the encapsulated function.
mat_plot(eg, xtemp, ytemp, dataNum, "-r", 1, 5);
The meaning of the above parameters
eg: pointer to the open matlab engine
xtemp: x coordinate data
ytemp: y-axis coordinate data
dataNum: the number of data
"-r": linetype, color (you can also set flags such as "-r*")
1: Line width
5: Marker size
This way you don't have to worry about how the data is passed to matlab and how the plot commands are run. If the encapsulation function is written better, it can be used more like in matlab, such as directly setting the line type and line width.
However, the commands of matlab are very large, and it is difficult to create a user-friendly, full-featured interface function library by only one person. Therefore, interested friends can contribute to this project. The project is stored on github: https://github.com/libing403/OTPL/tree/master/OTPL/TestDemo/MatlabEngineCode
To reference this interface function, you only need to include the two files MatlabEnginePlot.c and MatlabEnginePlot.h
As shown below
Everyone noticed that this matlab command function encapsulation function library interface is only a part of the code of the OTPL (Open Trajectory Planning Library) open source project, which is mainly used to test the c algorithm library for trajectory planning.
summary
In the past, when testing the c algorithm, it was necessary to transfer the data derivative generated by c to matlab, and then plot it to see the effect. In this way, it is necessary to write a C language program and a matlab program for testing, and it is particularly troublesome to draw dynamic graphics. Now, by calling the matlab engine directly in c/c++ for data visualization, almost all commands of matlab can be called in the C language environment. If the matlab command is encapsulated, it is as convenient as drawing in matlab, which can greatly improve the development efficiency.