|
本帖最后由 yangshangbin 于 2015-3-14 21:01 编辑
在C中调用Matlab
在C中调用Matlab 在用C写程序时,有时会遇到数值计算问题,如矩阵的计算、优化问题、解微分方程等等。这些数值计算问题如果自己来实现的话,一来太费时间,二来自己的实现方案效率未必高。所以遇到这些数值计算问题时可以先上网搜一下,看看有没有现成的模块(当然要可靠)。另一种解决方法就是依靠matlab了。用过matlab 的人都知道,它提供了丰富的数值计算函数。在C程序中调用matlab函数即可轻松解决问题。 在进行联合编程前需要经行配置
1 Visual Studio的配置(VS2008为例) 选择"工具"→"选项"→"VC++目录",如下图所示添加路径
2matlab的配置 在matlab命令行输入mex -setup,按提示选择合适的选项
在matlab命令行输入mbuild -setup,按提示选择合适的选项
以上配置只需进行一次就可以了,不必每写一个程序都重复一遍。
在C中调用matlab有两种方法:1 在C程序中调用matlab引擎 2 matlab函数编译生成dll文件供C程序使用。以下分别介绍
1在C程序中调用matlab引擎 为了调用matlab引擎,首先需要引入相应的头文件
#include "engine.h"
然后需要加如下几行代码,这样顺利地完成连接。
#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;
}
接下来将C程序中相关的变量变为matlab需要的格式,一般使用mxCreateDoubleMatrix 和 memcpy函数。
完成转换后使用engPutVariable将数据送到matlab引擎。
最后调用engEvalString,将matlab命令作为其参数,就可以利用matlab引擎进行计算了。
计算完成后不要忘了清理工作: 使用mxDestroyArray清除mxCreateDoubleMatrix产生的变量,最后使用engClose关闭引擎。
下面是一个例子,绘制y=sin(t)的图像
代码:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "engine.h"
#pragma comment( lib, "libeng.lib" )
#pragma comment( lib, "libmx.lib" )
#pragma comment( lib, "libmat.lib" )
int main()
{
Engine *ep;
if (!(ep = engOpen("\0")))
{
fprintf(stderr, "\nCan't start MATLAB engine\n");
return EXIT_FAILURE;
}
int Nsample = 50;
const double PI = 3.1415926;
double *t = new double[Nsample] ;
for(int i = 0; i < Nsample; i++)
{
t = 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);
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\n");
fgetc(stdin);
mxDestroyArray(T);
engEvalString(ep, "close;");
engClose(ep);
return EXIT_SUCCESS;
}
执行结果
2 C程序调用matlab生成的dll 如果需要matlab完成的功能比较通用,如果用上述方法,则会产生大量的重复代码。这里要讲的方法将对matlab 的调用做成一个模块,这样每次使用时只需调用这个模块就可以了。
首先将需要matlab完成的功能做成一个matlab函数,然后利用mcc命令编译,得到h、dll、lib等文件,在C工程中只需加入上述文件即可。下面是一个例子。
在做通信仿真时通常是给地一组信噪比,然后通过仿真得到在每个信噪比下的误码率,最后绘制出误码率对信噪比的曲线。
以前的做法是用C仿真,并将结果存在txt文件中,最后让matlab从txt文件中读取数据并绘图。
利用这里的方法,可以写一个matlab绘图的模块,并在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
得到一组文件
将其中的.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" )
下面的一段代码显示了调用绘图模块的方法:
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();
1在调用绘图模块之前需要调用showBERInitialize
2在调用绘图模块之后需要调用showBERTerminate
3使用mxCreateDoubleMatrix 和 memcpy 函数将C程序中的变量送入matlab中
4通过mlfShowBER调用matlab模块。而mlf***函数的调用格式需要参考***.h(此例为showBER.h)文件中的声明。
运行结果为
|
|
|