本文展示如何將 MATLAB 神經網絡工具箱編寫的 BP 神經網絡訓練/預測函數,打包為 COM 組件,並在 VC++ 中透過 VARIANT 型別實現高效數據交換,最終達成「VC 做界面、MATLAB 做算法」的工程化部署 (安裝包僅 3MB,無需目標機安裝 MATLAB)。
SJHSJY.mfunction [w1,b1,w2,b2,ET,a2] = SJHSJY(P,T,me,eg,lr,P2,T2,S1) % 輸入: P,T 訓練樣本; me 最大epoch; eg 誤差目標; lr 學習率; P2,T2 測試樣本; S1 隱層節點數 % 輸出: w1,b1,w2,b2 權重偏置; ET 訓練誤差; a2 測試輸出 [Pn,meanp,stdp,Tn,meant,stdt] = prestd(P,T); % 預處理標準化 [w1,b1,w2,b2] = initff(Pn,S1,'tansig',Tn,'purelin'); % 網絡初始化 df = 10; tp = [df me eg lr]; [w1,b1,w2,b2,tp,tr] = trainbpx(w1,b1,'tansig',...); % 訓練 (簡化) P2n = trastd(P2,meanp,stdp); % 測試樣本標準化 % ... 後處理反標準化、非負約束 ... a2 = max(a2, 0); % 確保非負 ET = ...; % 記錄誤差歷程
SJHSYC.mfunction [a2] = SJHSYC(P,T,P2,me,eg,lr,S1) % 僅預測,輸出 a2 [Pn,meanp,stdp,Tn,meant,stdt] = prestd(P,T); [w1,b1,w2,b2] = initff(Pn,S1,'tansig',Tn,'purelin'); % ... 同樣訓練流程 ... a2 = ...; % 返回預測結果
使用 MATLAB Deployment Tool (或 mcc -W com) 將上述兩個函數封裝為 COM 元件。專案名假設為 NeuralNetComp,類別分別為 ISJHSJY、ISJHSYC。
VC 選單 Project -> Add to Project -> Components and Controls -> Registered ActiveX Controls 找不到時,用 Project -> Add to Project -> Type Library 瀏覽生成的 .tlb 或直接 #import "NeuralNetComp.tlb" no_namespace。
ClassView 將出現 ISJHSJY、ISJHSYC 兩個介面類。

MATLAB 矩陣對應 COM SAFEARRAY,VC 需手動構建 VARIANT (VT_ARRAY | VT_R8)。
// 例:構建 4x6 雙精度二維陣列作為輸入參數 TTT SAFEARRAYBOUND rgsabound[2]; rgsabound[0].lLbound = 0; rgsabound[0].cElements = 4; // 行 rgsabound[1].lLbound = 0; rgsabound[1].cElements = 6; // 列 VARIANT TTT; VariantInit(&TTT); TTT.vt = VT_R8 | VT_ARRAY; TTT.parray = SafeArrayCreate(VT_R8, 2, rgsabound); // 複製資料 (假設 HH2 為 double[24] 連續記憶體) memcpy(TTT.parray->pvData, HH2, 24 * sizeof(double));
void CMyDlg::OnRunNetwork() {
if (FAILED(CoInitialize(NULL))) { AfxMessageBox(_T("COM初始化失敗")); return; }
ISJHSJY* pClass = NULL;
HRESULT hr = CoCreateInstance(CLSID_SJHSJY, NULL, CLSCTX_ALL, IID_ISJHSJY, (void**)&pClass);
if (FAILED(hr)) { AfxMessageBox(_T("COM組件建立失敗")); CoUninitialize(); return; }
// 準備輸入參數 VARIANT: PP, TTT, me, eg, lr, P2, T2, S1 ...
// 準備輸出參數 VARIANT: w1, b1, w2, b2, et, a2 (全部 VariantInit)
long nOutArgs = 6; // 輸出參數個數
hr = pClass->sjhsjy(nOutArgs, &w1, &b1, &w2, &b2, &et, &a2,
PP, TTT, var_me, var_eg, var_lr, var_P2, var_T2, var_S1);
if (SUCCEEDED(hr)) {
// 將輸出 VARIANT (SAFEARRAY) 複製回 double 陣列
double W1[420], W2[240], B1[60], B2[4], ET[4], A2[4];
memcpy(W1, w1.parray->pvData, 420*sizeof(double));
memcpy(W2, w2.parray->pvData, 240*sizeof(double));
memcpy(B1, b1.parray->pvData, 60*sizeof(double));
memcpy(B2, b2.parray->pvData, 4*sizeof(double));
memcpy(ET, et.parray->pvData, 4*sizeof(double));
memcpy(A2, a2.parray->pvData, 4*sizeof(double));
m_editResult.Format(_T("誤差: %.4f %.4f %.4f %.4f"), ET[0],ET[1],ET[2],ET[3]);
UpdateData(FALSE);
} else {
AfxMessageBox(_T("請輸入正確數據或檢查參數維度"));
}
pClass->Release();
CoUninitialize();
}
程式介面由 VC 構建,核心算法調用 MATLAB 神經網絡工具箱。打包部署後,目標機無需安裝 MATLAB (僅需 MCR),安裝包約 3MB。


VARIANT/SAFEARRAY 是 VC-MATLAB 數據交換的標準橋樑。SafeArrayCreate 或調用會失敗。作者 QQ: 44760299,歡迎技術交流。