MATLAB 強大的數學計算、工具箱與繪圖功能,配合 VC++ 的介面開發與部署能力,形成「VC 前台 + MATLAB 後台」經典架構。本文詳細說明三種混合模式、Engine 介面 API、VC6 專案設定、資料交換 (mxArray)、完整實作範例。
| 函數 | 功能 |
engOpen | 啟動 Engine,建立連接 |
engClose | 關閉 Engine |
engEvalString | 執行 MATLAB 命令字串 |
engGetVariable | 從工作區取得變數 (mxArray*) |
engPutVariable | 將變數放入工作區 |
engOutputBuffer | 設定輸出緩衝區捕獲 MATLAB 文字輸出 |
VC++ 6.0 專案設定步驟
- 包含目錄:Tools → Options → Directories → Include Files
D:\MATLAB6p5\extern\include
- 程式庫目錄:Library Files
D:\MATLAB6p5\extern\lib\win32\microsoft\msvc60
- 連結庫:Project → Settings → Link → Object/Library modules
libmx.lib libmat.lib libeng.lib
- 原始檔標頭:
#include "engine.h"
#include <stdlib.h>
Engine 初始化與錯誤處理
Engine* ep = engOpen("\0"); // 本地連接,傳空字串
if (!ep)
{
fprintf(stderr, "Can't start MATLAB engine\n");
exit(-1);
}
資料交換:VC 陣列 ↔ mxArray
核心函數:mxCreateDoubleMatrix、mxGetPr、memcpy
// VC double[] → mxArray (傳遞參數)
static double time[10] = {0,1,2,3,4,5,6,7,8,9};
mxArray* T = mxCreateDoubleMatrix(1, 10, mxREAL); // 1x10 矩陣
memcpy((char*)mxGetPr(T), (char*)time, 10 * sizeof(double));
engPutVariable(ep, "T", T); // 放入 MATLAB 工作區
// 執行 MATLAB 計算
engEvalString(ep, "D = .5 * (-9.8) * T.^5;"); // 向量運算
engEvalString(ep, "plot(T, D);"); // 繪圖視窗彈出
// mxArray → VC double[] (取回結果)
mxArray* D = engGetVariable(ep, "D");
double result[10];
memcpy((char*)result, (char*)mxGetPr(D), 10 * sizeof(double));
mxDestroyArray(D); // 釋放 mxArray
mxDestroyArray(T);
完整實作範例:拋體軌跡計算與繪圖
// 主視窗類別成員
Engine* m_ep = NULL;
void CMyView::OnCalculate()
{
if (!m_ep)
{
m_ep = engOpen("\0");
if (!m_ep) { AfxMessageBox("MATLAB Engine 啟動失敗"); return; }
}
// 1. 參數準備
double t[101];
for (int i = 0; i <= 100; i++) t[i] = i * 0.1; // 0~10秒
// 2. 傳遞時間向量
mxArray* T = mxCreateDoubleMatrix(1, 101, mxREAL);
memcpy((char*)mxGetPr(T), (char*)t, 101 * sizeof(double));
engPutVariable(m_ep, "t", T);
// 3. 執行計算: y = v0*sin(theta)*t - 0.5*g*t^2
engEvalString(m_ep, "v0 = 50; theta = pi/4; g = 9.8;");
engEvalString(m_ep, "y = v0*sin(theta)*t - 0.5*g*t.^2;");
// 4. 繪圖
engEvalString(m_ep, "figure; plot(t, y); xlabel('Time (s)'); ylabel('Height (m)'); title('Projectile Motion'); grid on;");
// 5. 取回結果 (可選)
mxArray* Y = engGetVariable(m_ep, "y");
double yResult[101];
memcpy((char*)yResult, (char*)mxGetPr(Y), 101 * sizeof(double));
// 繪製到 VC 視圖或存檔...
mxDestroyArray(T);
mxDestroyArray(Y);
}
void CMyView::OnDestroy()
{
if (m_ep) { engClose(m_ep); m_ep = NULL; }
CView::OnDestroy();
}
進階技巧與注意事項
- 非同步執行:Engine 為同步阻塞,長時間計算會凍結 UI。解法:Worker Thread 中呼叫 Engine API,或使用 MATLAB Compiler SDK 生成非阻塞 DLL。
- 記憶體管理:每個
mxArray* 必須配對 mxDestroyArray,否則洩漏。
- 矩陣維度:MATLAB 為 Column-Major,VC 為 Row-Major,傳遞 2D 矩陣需轉置或調整維度參數。
- 版本相容:VC6 對應 MATLAB 6.5/7.x (R13/R14),新版 MATLAB 需更新連結庫路徑。
- 錯誤捕獲:
engOutputBuffer 設定緩衝區可捕獲 MATLAB 錯誤訊息,便於除錯。
結語
MATLAB Engine 為 VC++ 提供了「即時 MATLAB 環境」的強大能力。掌握 engOpen/EvalString/PutVariable/GetVariable 核心流程、mxArray 與原生陣列的 memcpy 轉換、記憶體管理規範,即可構建「VC 介面 + MATLAB 計算核心」的專業工程應用。對於需部署免 MATLAB 環境的產品,建議進階採用 MATLAB Compiler SDK 生成 DLL 方案。
- 上一篇文章: VC++ 並口數據采集實作:AD7820 A/D 轉換電路與軟體控制
- 下一篇文章: 使用 VC++ 6.0 實作 JNI 完整範例教學
Copyright ©
程式碼之家 All Rights Reserved