matlab fgetc,C++ MATLAB 混合编程——VS项目调用MATLAB函数

引言

MATLAB无疑是一款强大的矩阵运算与数据分析软件,内部集成了众多函数。如果在C++编程时可以调用相关的函数将对我们的数据分析研究带来极大的方便。这里就总结一下如何在VS工程中调用MATLAB函数,以及遇到的问题如何解决的方法。

VS配置

这一步很重要,类似于其他C++库的配置,如:添加包含目录和库路径。

添加库目录(自己的MATLAB安装路径中查找):D:\Program Files (x86)\Matlab2018a\extern\include

faa4241cd67820c483df0bef53d0a44e.png

添加库路径(自己的MATLAB安装路径中查找):D:\Program Files (x86)\Matlab2018a\extern\lib\win64\microsoft

cc8c7b14a5e0f5414cd32f7242350eb4.png

配置系统环境变量

在Windows环境变量中的系统变量中“Path”中新增下面三项:

D:\Program Files (x86)\Matlab2018a\bin; (安装MATLAB后已经存在不用再添加)

D:\Program Files (x86)\Matlab2018a\bin\win32;

D:\Program Files (x86)\Matlab2018a\bin\win64

2138f562ced81f964a91b6f3ab2a98dc.png

MATLAB配置

在Matlab的command window输入:mex -setup

选择:mex -setup C++

13f9a017ea4b4ea34398c378ad990e85.png

然后再输入:mbuild -setup

选择:mex -setup C++ -client MBUILD

eab62b05e1a1fe882daff17de5cfdc32.png

配置结束

b7d68a322002adf5ddba0b8bc69b34cf.png

测试

我们将在VS2013 的C++项目中调用MATLAB,调用方式有两种:(1)调用MATLAB引擎; (2)调用MATLAB函数生成的DLL。

方式1调用MATLAB引擎

首先,添加头文件 #include “engine.h”

然后,引用函数调用依赖库(lib) libeng.lib libmx.lib libmat.lib,之后就可以调用MATLAB引擎。

// import necessary lib

#pragma comment( lib, "libeng.lib")

#pragma comment( lib, "libmx.lib")

#pragma comment( lib, "libmat.lib")

MATLAB引擎调用和文件操作类似:打开、关闭操作。

打开引擎:

Engine *ep;

if (!(ep = engOpen("\0")))

{

fprintf(stderr, "\nCan't start MATLAB engine\n");

return EXIT_FAILURE;

}

定义变量需要转换为matlab的格式。比如使用:mxCreateDoubleMatrix 和 memcpy函数。

将数据传入引擎使用:engPutVariable()。接着调用 engEvalString(ep, “matlab指令”)matlab的指令作为参数进行操作。计算操作等完成后需要清理操作:mxDestroyArray()函数清理mxCreateDoubleMatrix 生成的变量。

engClose()关闭引擎。

完整绘图例子:

#include

#include

#include

#include "engine.h" // add header file

// import necessary lib

#pragma comment( lib, "libeng.lib")

#pragma comment( lib, "libmx.lib")

#pragma comment( lib, "libmat.lib")

int main(void)

{

Engine *ep;

// open engine

if (!(ep = engOpen("\0")))

{

fprintf(stderr, "\nCan't start MATLAB engine\n");

return EXIT_FAILURE;

}

// generate variables

int Nsample = 50;

const doublePI= 3.1415926;

double *t = new double[Nsample];

for (int i = 0; i < Nsample; i++)

{

t[i] = i * 2 *PI/ Nsample;

}

mxArray *T = NULL, *result = NULL;

T= mxCreateDoubleMatrix(1, Nsample, mxREAL);

memcpy((void *)mxGetPr(T), (void *)t, Nsample*sizeof(t[0]));

engPutVariable(ep, "T", T); // put data to engine

// execute matlab operations

engEvalString(ep, "Y=sin(T);");

engEvalString(ep, "plot(T,Y);");

engEvalString(ep, "title('y=sin(t)');");

engEvalString(ep, "xlabel('t');");

engEvalString(ep, "ylabel('y');");

printf("Hit return to continue\n");

fgetc(stdin);

// clean operation(don't forget!!!)

mxDestroyArray(T);

engEvalString(ep, "close;");

// close engine

engClose(ep);

return EXIT_SUCCESS;

}

效果:

03cfcf2d0a33e1a1830ebaac98272543.png

出现错误解决方法:

1>------ 已启动生成: 项目: CMatlab, 配置: Debug Win32 ------

1>main.obj : error LNK2019: 无法解析的外部符号 _mxGetPr_800,该符号在函数 _main 中被引用

1>main.obj : error LNK2019: 无法解析的外部符号 _mxDestroyArray_800,该符号在函数 _main 中被引用

1>main.obj : error LNK2019: 无法解析的外部符号 _mxCreateDoubleMatrix_800,该符号在函数 _main 中被引用

1>main.obj : error LNK2019: 无法解析的外部符号 _engEvalString,该符号在函数 _main 中被引用

1>main.obj : error LNK2019: 无法解析的外部符号 _engOpen,该符号在函数 _main 中被引用

1>main.obj : error LNK2019: 无法解析的外部符号 _engClose,该符号在函数 _main 中被引用

1>main.obj : error LNK2019: 无法解析的外部符号 _engPutVariable,该符号在函数 _main 中被引用

1>E:\shizhenwei\VS2013Projects\CMatlab\Debug\CMatlab.exe : fatal error LNK1120: 7 个无法解析的外部命令

这个问题出在兼容上。我们需要将vs工程变为64位,然后即可解决。

方式2调用MATLAB生成的dll

调用MATLAB生成的DLL是一种比较通用的方法,这样每次使用时只需调用这个模块就可以了。

首先,将需要MATLAB完成的功能做成一个MATLAB函数。

然后,利用mcc命令编译,得到h、dll、lib等文件,在C/C++工程中只需加入上述文件即可。

MATLAB函数代码

function showBER(SNR_indB,BER) semilogy(SNR_indB,BER,'-o','linewidth',2);

grid on

xlabel('E_b/N_0(dB)');

ylabel('BER');

编译后,在MATLAB命令行中输入:

mcc -B csharedlib:showBER showBER.m

得到一组文件

a7f90a69f256ec46da94d24792be2c25.png

将其中的.dll .h .lib文件拷贝到C工程中,在需要调用绘图模块的cpp文件中加入如下代码:

#include "showBER.h"

#pragma comment( lib, "libeng.lib" )

#pragma comment( lib, "libmx.lib" )

#pragma comment( lib, "libmat.lib" )

#pragma comment( lib, "mclmcrrt.lib" )

#pragma comment( lib, "showBER.lib" )

void main(void)

{

double SNR[] = { 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5 };

double BER[] = { 9.728816e-002, 8.099609e-002, 5.633803e-002, 3.733608e-002, 1.253970e-002, 3.936489e-003, 1.206820e-003, 2.104052e-004, 3.109879e-005, 3.365857e-006, 2.565067e-007 };

int len = sizeof(SNR) / sizeof(SNR[0]);

showBERInitialize();

mxArray* xSNR = mxCreateDoubleMatrix(1, len, mxREAL);

memcpy(mxGetPr(xSNR), (void*)SNR, sizeof(SNR));

mxArray* xBER = mxCreateDoubleMatrix(1, len, mxREAL);

memcpy(mxGetPr(xBER), (void*)BER, sizeof(BER));

mlfShowBER(xSNR, xBER);

system("PAUSE");

showBERTerminate();

}

运行效果

de7f80a2d241140deb33671be1201619.png

提示

其他打包方法可以参考3和4链接中的介绍,亲测可用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值