在用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] = 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)文件中的聲明。
運行結果爲