當(dāng)前位置:首頁 > EDA > 電子設(shè)計(jì)自動(dòng)化
[導(dǎo)讀]基于COM組件的Matlab與C++混合編程方式因擁有獨(dú)立的運(yùn)行環(huán)境和兩種語言的互補(bǔ)優(yōu)勢(shì)而被眾多科研人員和編程人員所接受,同時(shí)也是MathWorks公司推薦使用的混編方式。但在程序設(shè)計(jì)過程中,通常會(huì)遇到兩個(gè)難點(diǎn)問題:(1)二

基于COM組件的Matlab與C++混合編程方式因擁有獨(dú)立的運(yùn)行環(huán)境和兩種語言的互補(bǔ)優(yōu)勢(shì)而被眾多科研人員和編程人員所接受,同時(shí)也是MathWorks公司推薦使用的混編方式。但在程序設(shè)計(jì)過程中,通常會(huì)遇到兩個(gè)難點(diǎn)問題:(1)二維數(shù)組參數(shù)的傳遞與輸出; (2)Matlab生成圖形嵌入VC工程界面中。對(duì)于第一個(gè)問題,Bruce McKinney[1]在MSDN上指出;“如果對(duì)一維數(shù)組進(jìn)行操作,則SAFEARRAY函數(shù)變的簡(jiǎn)單且易操作。但是對(duì)于多維數(shù)組,同樣的操作要復(fù)雜得多”,造成這一問題的根源在于Matlab與C++對(duì)多維數(shù)組元素的存儲(chǔ)方式不同。而在本項(xiàng)目開發(fā)過程中回避了這個(gè)復(fù)雜的過程,轉(zhuǎn)而利用Matlab強(qiáng)大的數(shù)組處理功能將其解決。Matlab完善的圖形處理功能是其被科研人員所推崇的原因之一,但因其圖形擁有獨(dú)立的窗口,嚴(yán)重影響了整體界面美觀和用戶交互體驗(yàn),所以Matlab圖形嵌入是混合編程中不可回避的問題。對(duì)此將通過實(shí)例介紹兩種圖形嵌入方法并分析說明其優(yōu)缺點(diǎn)和相關(guān)細(xì)節(jié)。

本文示例均在Matlab R2008a和VC 6.0平臺(tái)下完成,且通過調(diào)試能夠正常運(yùn)行。

1 Excel文件讀取方法

VC平臺(tái)下的Excel文件讀取方式復(fù)雜難懂,但如果使用Matlab與VC的混合編程方式編寫將更加簡(jiǎn)便,而且擁有較強(qiáng)的可擴(kuò)展性。下面代碼詳細(xì)講解了該過程。

(1)在Matlab平臺(tái)下建立CExcelRead.m文件,代碼如下:

function [output,row,col] = CExcelRead(filePath)

//filePath包含了指定文件的路徑和文件名,由VC平臺(tái)函數(shù)GetPathName()獲取

[typ, desc] = xlsfinfo(filePath);

//xlsfinfo()可獲取指定Excel文件中各個(gè)sheet工作區(qū)的名稱,返回值存入名為desc的cell數(shù)組中

sheet1 = cell2mat(desc(1));

//默認(rèn)打開”sheet1”(名稱任意),并將其轉(zhuǎn)換為字符串

output = xlsread(filePath,sheet1);

//返回該Excel文件中的數(shù)據(jù),返回值存入output數(shù)組中

[row,col] = size(output);

//獲取錄入數(shù)據(jù)的行列值,返回到VC平臺(tái)以供其拷貝指定內(nèi)存大小的數(shù)據(jù)

output = reshape(output,row*col,1);

//將該二維數(shù)組轉(zhuǎn)換為一維。這是第二部分二維數(shù)組處理的第一步

保存文件后,使用deploytool工具將其制作成名為FileOpen的COM(封裝MCR),注冊(cè)該控件并將相應(yīng)的文件拷貝到MFC的工程中,對(duì)于基礎(chǔ)操作此處不再贅述。

(2)在VC平臺(tái)下創(chuàng)建名為PCA的基于對(duì)話框的MFC工程,添加一打開文件的按鈕控件,ID為ID_FILE_OPEN。篇幅所限只給出部分核心代碼,首先在Dlg類中添加3個(gè)私有成員變量用以保存Matlab讀取的數(shù)據(jù)及行列值,即:

double *m_originData; long m_row, m_col;

在響應(yīng)函數(shù)中添加如下代碼

CFileDialog fileDlg(TRUE);

fileDlg.m_ofn.lpstrTitle="請(qǐng)選擇你的excel數(shù)據(jù)";

fileDlg.m_ofn.lpstrFilter="Text Files(*.xls)*.xlsAll Files(*.*)*.*";

if(IDOK==fileDlg.DoModal() {

CString fileName; IFileOpenclass *pfile;

VARIANT filePath,output,rowOutput,colOutput;

//m文件的輸入?yún)?shù)

fileName = fileDlg.GetPathName();

//獲取文件路徑并存于fileName中

CoInitialize(NULL); //COM初始化

HRESULT hr = CoCreateInstance(CLSID_FileOpenclass,NULL,CLSCTX_ALL,IID_IFileOpenclass,(void**)&pfile);

//新建COM實(shí)例

VariantInit(&filePath); //VARIANT數(shù)據(jù)初始化

filePath.vt = VT_BSTR; //指定filePath變量類型

//將fileName中保存的指定文件路徑名保存至filePath參數(shù)中

filePath.bstrVal = fileName.AllocSysString();

pfile->CExcelRead(3,&output,&rowOutput, &colOutput,filePath);

m_row=(long) rowOutput.dblVal;

//取出行列值及錄入數(shù)據(jù)

m_col = (long) colOutput.dblVal;

m_originData = (double *)malloc(sizeof(double)*m_row*m_

col); memcpy(m_originData,output.parray->pvData,m_row*m_

col*sizeof(double));

//將matlab讀入數(shù)據(jù)保存到m_originData供后面程序使用

}

上述C++代碼中省略了異常處理和相關(guān)的內(nèi)存、COM釋放代碼,由于代碼比較簡(jiǎn)單所以不做進(jìn)一步解析。請(qǐng)注意,下面將省略COM初始化及實(shí)例化等相同代碼。

(3) 需要重點(diǎn)說明的是該方法的擴(kuò)展性。通常Excel文件中保存多個(gè)工作區(qū),有時(shí)用戶可能需要打開同一Excel文件中不同工作區(qū)中的數(shù)據(jù),常規(guī)方法實(shí)現(xiàn)過于復(fù)雜,但對(duì)于本文介紹的方法可以通過修改添加幾條語句即可實(shí)現(xiàn)。首先,新建一個(gè)m文件用來處理工作區(qū)的選擇,代碼如下:

function [sheet,col] = CSheetSelected(filePath)

[typ, sheet] = xlsfinfo(filePath);

[row,col] = size(sheet);

由于返回值是一個(gè)cell數(shù)組,所以VC平臺(tái)要使用CStringArray數(shù)據(jù)結(jié)構(gòu)保存返回值,并顯示各工作區(qū)名稱供用戶選擇。然后,通過人機(jī)交互將用戶選擇的工作區(qū)參數(shù)保存并傳遞至CExcelRead.m,通過在CExcelRead.m增加一個(gè)工作區(qū)選擇參數(shù),并對(duì)代碼稍作修改即可。

2 二維數(shù)組參數(shù)的傳遞與輸出[2]

下面以主成分分析為例介紹基于COM的Matlab與VC混合編程中二維數(shù)組參數(shù)處理。

(1) 主成分分析pcamat.m代碼如下:

function [eigenvector,eigenvalue] = pcamat(oriData,row,column)

//在Excel讀入時(shí)已經(jīng)完成了二維數(shù)組輸出的關(guān)鍵步驟,即輸出時(shí)將二維數(shù)組轉(zhuǎn)換為一維數(shù)組。但在VC平臺(tái)接收還原為二維時(shí)要注意,Matlab數(shù)組存儲(chǔ)方式是按列存儲(chǔ),而VC平臺(tái)下數(shù)組是按行存儲(chǔ),所以轉(zhuǎn)換時(shí)0~row-1為第一列,row~2*row-1為第二列,以此類推。本文輸入?yún)?shù)oriData是一維數(shù)組,所以要將其還原為二維數(shù)組使Matlab程序能夠正常運(yùn)行,即下一行代碼所示。

oriData = reshape(oriData,row,column);

dataSTD=std(oriData,0,1); dataMean = mean(oriData);

dataSR = (oriData-dataMean(ones(row,1),:))./dataSTD(ones(row,1),:);

[eigenvector,newdata,eigenvalue,Exa]=princomp(dataSR);

//第三行至此處均為主成分分析內(nèi)容

eigenvector = reshape(eigenvector,column*column,1);

//與Excel文件讀取時(shí)類似,將二維輸出轉(zhuǎn)換為一維數(shù)組進(jìn)行輸出

(2) 保存后,封裝打包為COM組件,并完成注冊(cè)等相關(guān)操作。在PCA工程對(duì)話框上添加一個(gè)名為PCATest的按鈕控件,核心代碼如下:

VARIANT oriData,row,column,eigVector,eigValue;

VariantInit(&oriData); //參數(shù)初始化

oriData.vt = VT_R8|VT_ARRAY;

//定義SAFEARRAY類型的一維數(shù)組

SAFEARRAYBOUND rgsadound[1];

rgsadound[0].lLbound = 0;

rgsadound[0].cElements = m_row*m_col;

oriData.parray = SafeArrayCreate(VT_R8,1,rgsadound);

oriData.parray->pvData = m_originData;

//完成相關(guān)設(shè)置后,將第一步讀入的數(shù)據(jù)錄入到oriData中,即賦給pcamat的oriData。到此完成了二維數(shù)組的傳遞

row.vt = VT_I4; col.vt = VT_I4;

row.lVal = m_row; col.lVal = m_col;

pca->pcamat(2,&eigVector,&eigValue,oriData,row,col);

memcpy(result, eigVector.parray->pvData,m_col*m_col*

sizeof(double));

綜上,二維數(shù)組參數(shù)處理就是使用reshape()函數(shù)對(duì)輸入輸出數(shù)據(jù)維數(shù)進(jìn)行變換來完成操作。

3 Matlab圖像嵌入VC界面[3]

3.1 基于CWnd類的圖像嵌入

在Windows操作系統(tǒng)下,所有應(yīng)用程序的窗口都是基于MFC中的CWnd類。所以可以通過調(diào)用該類或其派生類中的方法實(shí)現(xiàn)圖像嵌入?;舅枷耄涸贛atlab平臺(tái)下用COM封裝產(chǎn)生圖形窗口的程序;在VC平臺(tái)獲取Figure窗口的句柄,將Figure窗口設(shè)為VC程序的子窗口;(3)將Figure窗口移動(dòng)到指定顯示位置。

程序?qū)崿F(xiàn)如下:

(1)將原pcamat.m進(jìn)行修改,添加生成圖像的相關(guān)代碼

function [eigenvector,eigenvalue] = pcamat(oriData,row,column,picName)

//增加picName參數(shù),VC平臺(tái)下hFig將通過該名稱獲取生成圖像的句柄

figure("NumberTitle","Off","MenuBar","None","ToolBar","Figure","Name",picName,"Units","Points");

//圖像參數(shù)預(yù)設(shè),保留工具欄。使用Matlab提供的工具欄的所有功能是使用該方法的最大優(yōu)點(diǎn)

percent = 100*eigenvalue /sum(eigenvalue);

//計(jì)算貢獻(xiàn)率

pareto(percent); //畫圖

xlabel("主成分");

ylabel("方差占的比重(%)");

(2)封裝打包成名為figure的COM組件,并完成注冊(cè)等相關(guān)操作。因?yàn)樾薷暮蟮膍文件運(yùn)行結(jié)果包含輸出結(jié)果和圖像兩部分,所以下面有關(guān)圖像處理的代碼依然在PCATest控件的響應(yīng)函數(shù)中。

CString WNDName = "Demo"; //自定義窗口名稱

Ifigureclass *pic;

VARIANT oriData, row, col, picName,eigVector, eigValue; VariantInit(&picName);

……

picName.vt = VT_BSTR; //將自定義窗口名稱賦予

Matlab生成圖像

picName.bstrVal = WNDName.AllocSysString();

HWND hFig; int timer = 50;

//用死循環(huán)確??梢垣@取到圖像句柄,注意此處必須使用sleep(),給予系統(tǒng)足夠的響應(yīng)時(shí)間

while(1){

pic->pcamat(2,&eigVector,&eigValue,oriData,row,col,

picName);

Sleep(timer);

hFig = ::FindWindow(NULL,FigName);

if(hFig != NULL){

break;

}

timer += 10;

pic->Release();

}

long lStyle = ::GetWindowLong(hFig,GWL_STYLE); //設(shè)置Figure窗口樣式。

//注意SetWindowLong()和SetWindowPos()先后順序,詳見MSDN

::SetWindowLong(hFig,GWL_STYLE,lStyle&(~WS_CAPTION)&(~WS_THICKFRAME))

::SetWindowPos(hFig,NULL,0,0,0,0,SWP_NOMOVE|SWP_

NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_

FRAMECHANGED);CRect PlotRec;

CWnd *PlotArea = GetDlgItem(IDC_STATIC_FIGURE); //設(shè)置圖像顯示區(qū)域

PlotArea->GetWindowRect(&PlotRec);

long Width = PlotRec.right - PlotRec.left;

long Height = PlotRec.bottom - PlotRec.top;

::SetParent(hFig,PlotArea->GetSafeHwnd());

//設(shè)置圖像的父窗口

::SetWindowPos(hFig,NULL,0,0,Width,Height,SWP_NOZORDER|SWP_NOACTIVATE);

該方法的缺點(diǎn)是,在圖像生成時(shí)會(huì)有閃爍現(xiàn)象。而優(yōu)點(diǎn)是前面提到的可以繼續(xù)使用Matlab提供的工具欄。鑒于該缺點(diǎn)影響整體美觀,所以引入下面第二種方法。

3.2基于Bitmap類的圖像嵌入

通過Bitmap類將Matlab生成的.bmp文件加載到VC工程中,使用Bitmap類中的成員函數(shù)對(duì)圖像進(jìn)行處理。由于相關(guān)函數(shù)可以通過幫助手冊(cè)獲取,所以此處不再給出相應(yīng)代碼,運(yùn)行結(jié)果如圖2所示。該方法避免了方法一生成圖像時(shí)的閃爍現(xiàn)象,但是BMP圖像顯示效果較差而且無法使用Matlab提供的工具菜單,這是其不足之處。

使用COM組件進(jìn)行混合編程時(shí),往往習(xí)慣于在VC平臺(tái)下思考所遇到的問題,但是這樣不僅使得問題可能變得復(fù)雜化,或得不到妥善解決,而且也違背了“混合”的初衷。二維數(shù)組參數(shù)處理就是一個(gè)很好的例證。其次,充分利用Matlab特性可以使得程序具備良好的擴(kuò)展性和穩(wěn)定性,對(duì)Excel文件讀取方式進(jìn)行的擴(kuò)展,明顯使軟件更加人性化。對(duì)于圖像嵌入問題,雖然文中提出的兩種嵌入方式可以滿足基本需求,但是仍然存在一些瑕疵,還需要進(jìn)一步研究。

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

倫敦2024年8月29日 /美通社/ -- 英國(guó)汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動(dòng) BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對(duì)日本游戲市場(chǎng)的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對(duì)環(huán)境變化,經(jīng)營(yíng)業(yè)績(jī)穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤(rùn)率延續(xù)升勢(shì) 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長(zhǎng) 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競(jìng)爭(zhēng)力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競(jìng)爭(zhēng)優(yōu)勢(shì)...

關(guān)鍵字: 通信 BSP 電信運(yùn)營(yíng)商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺(tái)與中國(guó)電影電視技術(shù)學(xué)會(huì)聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會(huì)上宣布正式成立。 活動(dòng)現(xiàn)場(chǎng) NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長(zhǎng)三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會(huì)上,軟通動(dòng)力信息技術(shù)(集團(tuán))股份有限公司(以下簡(jiǎn)稱"軟通動(dòng)力")與長(zhǎng)三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉