???????? 目錄
??????? com方式調(diào)用matlab(一)
??????? com方式調(diào)用matlab(二)?
??????? com方式調(diào)用matlab(三)
??????? com方式調(diào)用matlab(四)?
??????? com方式調(diào)用matlab(五)
??????? com方式調(diào)用matlab(六)
??????? com方式調(diào)用matlab(附:運(yùn)行結(jié)果及代碼)
??????? 在前面粗略描述了系統(tǒng)的設(shè)計(jì)思路和matlab生成com組件的相關(guān)知識后,從現(xiàn)在開始,將要討論一下具體的實(shí)現(xiàn)方面的問題.在本部分,我們首先討論一下配置文件的格式和內(nèi)容,然后再探討一下以com方式調(diào)用matlab進(jìn)行繪圖的相關(guān)技術(shù).
??????? 前面曾經(jīng)說到過我們將要把matlab所生成的組件的相關(guān)信息,包括組件GUID,接口RIID以及方法參數(shù)寫到一個(gè)配置文件里面去,這樣我們的vc程序就能夠以可擴(kuò)充的方式使用matlab組件了.下面是我所設(shè)計(jì)的配置信息的一個(gè)例子:
<?
xml?version="1.0"?encoding="utf-8"
?>
<
Components
>
????
<
Graph?
physicalName
="c1_1_0.dll"
?Name
="圖1"
>
????????
<
GUID
>
{8DE06792-8F2B-48CB-9908-080A572802CD}
</
GUID
>
????????
<
RIID
>
{0A0A6D93-0CE5-4228-A5B2-999691D2DE55}
</
RIID
>
????????
<
Method
>
????????????
<
MethodName
>
draw2d
</
MethodName
>
????????
</
Method
>
????
</
Graph
>
????
<
Graph?
physicalName
="c2_1_0.dll"
?Name
="圖2"
>
????????
<
GUID
>
{13270AAA-5E35-4E91-A8F0-C275C0D5F664}
</
GUID
>
????????
<
RIID
>
{56C22D9C-EC7E-4708-AF2C-98C8C5FC7F24}
</
RIID
>
????????
<
Method
>
????????????
<
MethodName
>
drawline2d
</
MethodName
>
????????????
<
Param?
Name
="x1"
>
5
</
Param
>
????????????
<
Param?
Name
="x2"
>
-5
</
Param
>
????????????
<
Param?
Name
="a"
>
-10
</
Param
>
????????????
<
Param?
Name
="b"
>
10
</
Param
>
????????
</
Method
>
????
</
Graph
>
????
<
Graph?
physicalName
="c3_1_0.dll"
?Name
="圖3"
>
????????
<
GUID
>
{9E2B0F53-6638-446D-A292-A0BF9F17656D}
</
GUID
>
????????
<
RIID
>
{FC8A4C39-4B83-46AF-AC71-259CE1791037}
</
RIID
>
????????
<
Method
>
????????????
<
MethodName
>
drawline3d
</
MethodName
>
????????????
<
Param?
Name
="x1"
>
7
</
Param
>
????????????
<
Param?
Name
="x2"
>
-7
</
Param
>
????????????
<
Param?
Name
="y1"
>
8
</
Param
>
????????????
<
Param?
Name
="y2"
>
-8
</
Param
>
????????????
<
Param?
Name
="n"
>
20
</
Param
>
????????
</
Method
>
????
</
Graph
>
????
<
Graph?
physicalName
="darw123_1_0.dll"
?Name
="圖4"
>
????????
<
GUID
>
{F2C933B5-E83D-40F0-9A6D-3EF822933172}
</
GUID
>
????????
<
RIID
>
{4151A20D-6F6C-4EBB-8830-D7D66AD250B5}
</
RIID
>
????????
<
Method
>
????????????
<
MethodName
>
draw123
</
MethodName
>
????????????
<
Param?
Name
="x2"
>
7
</
Param
>
????????????
<
Param?
Name
="x1"
>
-7
</
Param
>
????????????
<
Param?
Name
="b"
>
8
</
Param
>
????????????
<
Param?
Name
="a"
>
4
</
Param
>
????????
</
Method
>
????
</
Graph
>
</
Components
>
??? 上面的配置文件里面包含三個(gè)圖像的配置,分別是圖
1
,圖
2
和圖
3
。他們具有相同的結(jié)構(gòu)。下面分別說一下配置文件各個(gè)部分的信息。
???????? Component
作為配置文件的根存在。
?????????Graph
子節(jié)點(diǎn)代表一個(gè)圖。仔細(xì)看一下,
Graph
子節(jié)點(diǎn)又包含以下子節(jié)點(diǎn):
???????? GUID
:組件的全局
ID
。他用來唯一標(biāo)示一個(gè)組件。
???????? RIID
:接口相對于組件的
ID
。通過
GUID
、
RIID
你就可以唯一找到你想構(gòu)建的那個(gè)接口。
???????? Method
:接口方法。其中的
MethodName
為接口方法的名稱;
Param
為接口方法的參數(shù)。
Param
的
Name
屬性為借口方法參數(shù)的名稱。
????另外,
Graph
節(jié)點(diǎn)包含兩個(gè)屬性。其中:
????????PhysicalName
為組件文件的物理路徑。
vc程序
根據(jù)這個(gè)物理路徑來找到組件。其實(shí)對于組件來講,在注冊表中進(jìn)行注冊以后,就在相應(yīng)系統(tǒng)中建立了組件的全局索引。任何程序只要根據(jù)
GUID
和
RIID
就可以找到組件,完全不需要知道物理路徑。但是在開發(fā)程序的時(shí)候,本著這樣一個(gè)宗旨,就是讓軟件綠色一些,盡量在不注冊的前提下使用組件。當(dāng)然基于
Matlab
組件對于一些核心模塊的依賴,這種思路沒有成功。但是這種調(diào)用方式對于其他程序而言是可以借鑒的。所以這里還是維持了這種思路。
????????Name
為組件顯示名稱。
vc程序
中根據(jù)這個(gè)名稱創(chuàng)建下拉列表供用戶進(jìn)行選擇。
??? 下面依照一個(gè)例子來說明配置文件是如何進(jìn)行編寫的。
????
???? 在這里創(chuàng)建的組件的名稱為
c2
。在
c2
組件的工作目錄中(具體見com方式調(diào)用matlab(二)),進(jìn)入
src
目錄,打開
c2_idl_i.c
文件。如下圖所示的信息為我們需要填入
xml
的信息。
???? 
??? 可以看到,上面的為
RIID
,下面的為
GUID
。那么如何進(jìn)行區(qū)別呢?
GUID
一般是以
CLSID
為前綴的。而
RIID
是以
IID
為前綴的。值得注意的是,這里要將
GUID
和
RIID
修改成
8-4-4
-4-12
(
16
進(jìn)制)的形式。否則在
CM
中無法識別。在得到這兩個(gè)信息以后,我們再去找到接口方法的相關(guān)信息。打開
c2_com.cpp
文件,會看到如下信息:
??? 
???? 這里就是接口方法了.把相關(guān)信息填入method節(jié)點(diǎn),一個(gè)matlab圖的配置就寫完了.值得注意的是,matlab接口方法的參數(shù)順序和我們調(diào)用的順序剛好相反,比如對于上面的方法聲明,我們在配置里面就得這么寫:
???? 
?????具體原因可能和參數(shù)的壓棧方法有關(guān),這里我也沒有深究,如果有人對于具體細(xì)節(jié)了解的比較詳細(xì),希望您能不吝賜教.
?????通過上面的步驟,我們就完成了配置文件的設(shè)計(jì)并完成了一個(gè)例子.下面來看一看使用matlab組件的具體方法.
???? 其實(shí)通過com方式調(diào)用matlab進(jìn)行圖形繪制確實(shí)不難,對于稍有com組件知識的人來講,尤為如此.簡單的講,首先使用DllGetClassObject函數(shù)創(chuàng)建類廠,然后用類廠獲取IDispatch接口,然后用IDispatch接口通過方法的名稱調(diào)用方法.下面是具體的實(shí)現(xiàn):
????
bool
?CMatlabGraph::DrawGraph(CString?sGraphName)
//
繪圖
{
????
if
(
!
this
->
m_pcfg)

????
{
????????
this
->
m_sError
=
"
獲取配置文件失敗!
"
;
????????
return
?
false
;
????}
????
if
(
!
m_pcfg
->
FindGraphInfoByName(
this
,sGraphName))

????
{
????????
this
->
m_sError
=
m_pcfg
->
m_sError;
????????
return
?
false
;
????}
????::CoInitialize(NULL);
????IDispatch?
*
pIDisp
=
NULL;
????
//
指向讀入的組件文件的句柄
????HINSTANCE?hinstLib;
????
//
指向類廠的實(shí)例化方法
????MYPROC?ProcAdd;
????BOOL?fRunTimeLinkSuccess?
=
?FALSE;
????
//
int?rtn=0;
????
//
讀取組件文件載入內(nèi)存
????hinstLib?
=
?LoadLibrary(
this
->
m_sComFileName.GetBuffer(m_sComFileName.GetLength()));
????
//
如果執(zhí)行成功,則hinstLib非空
????
if
?(hinstLib?
!=
?NULL)?

????
{
????????
//
讀取指向獲取類廠的函數(shù)的指針
????????ProcAdd?
=
(MYPROC)GetProcAddress(hinstLib,?
"
DllGetClassObject
"
);
????????
//
?如果獲取成功,則創(chuàng)建類廠
????????
if
?(fRunTimeLinkSuccess?
=
?(ProcAdd?
!=
?NULL))

????????
{
????????????
//
類廠接口
????????????IClassFactory?
*
pIf;
????????????
//
初始類廠接口為空
????????????pIf
=
NULL;
????????????
if
(SUCCEEDED(ProcAdd(m_clsid,IID_IClassFactory,(
void
?
**
)
&
pIf))
&&
(pIf
!=
NULL))

????????????
{
????????????????
if
(
!
SUCCEEDED(pIf
->
CreateInstance(NULL,m_riid,(
void
?
**
)
&
pIDisp))
||
(pIDisp
==
NULL))

????????????????
{
????????????????????????pIf
->
Release();
????????????????????????pIf
=
NULL;
????????????????????????FreeLibrary(hinstLib);
????????????????????????::CoUninitialize();
????????????????????????
return
?
false
;
????????????????}
????????????????m_hinstLib
=
hinstLib;
????????????????
//
因?yàn)橐呀?jīng)取得分發(fā)接口,故釋放類廠接口
????????????????pIf
->
Release();
????????????????pIf
=
NULL;
????????????????
//
根據(jù)名稱查找接口方法
????????????????USES_CONVERSION;
????????????????OLECHAR?FAR
*
?szMember?
=
?T2OLE((LPCTSTR)(
this
->
m_sMethodName.GetBuffer(
this
->
m_sMethodName.GetLength())));
????????????????
//
獲取方法ID
????????????????DISPID?MethodID;
????????????????
if
(
!
SUCCEEDED(pIDisp
->
GetIDsOfNames(IID_NULL,
&
szMember,
1
,LOCALE_SYSTEM_DEFAULT,
&
MethodID)))

????????????????
{
????????????????????
this
->
m_sError
=
"
取接口方法ID失敗
"
;
????????????????????
return
?
false
;
????????????????}
????????????????
//
填入?yún)?shù)
????????????????DISPPARAMS?dispparams?
=
?
{?
this
->
m_pvars,?NULL,?
this
->
m_nparacount,?
0
}
;
????????????????
//
調(diào)用方法
????????????????HRESULT?hr
=
pIDisp
->
Invoke(MethodID,IID_NULL,GetUserDefaultLCID(),DISPATCH_METHOD,
&
dispparams,NULL,NULL,NULL);
????????????????
if
(
!
SUCCEEDED(hr))

????????????????
{
????????????????????
this
->
m_sError.Format(
"
調(diào)用失敗!錯(cuò)誤碼:%x
"
,hr);?
//
="調(diào)用失敗!";
????????????????????FreeLibrary(hinstLib);
????????????????????::CoUninitialize();
????????????????????
return
?
false
;
????????????????}
????????????????
//
釋放文件
????????????????
//
FreeLibrary(hinstLib);
????????????????
//
::CoUninitialize();
????????????????
return
?
true
;????
????????????}
????????}
????}
????::CoUninitialize();
????
return
?
false
;
}
??????? 下面是CMatlabGraph的類定義:
class?CMatlabGraph??


{
public:
????CMatlabGraph(CGraphConfiguration?*cfg);
????virtual?~CMatlabGraph();
????bool?DrawGraph(CString?sGraphName);//繪圖
????CString?m_sError;//錯(cuò)誤信息
private:
????CLSID?m_clsid;//組件對象ID
????IID?m_riid;//接口ID
????CString?m_sMethodName;//接口方法名稱
????CString?m_sComFileName;//組件文件名稱
????CComVariant?*m_pvars;//接口方法參數(shù)
????CGraphConfiguration?*m_pcfg;//配置
????int?m_nparacount;//接口方法參數(shù)個(gè)數(shù)
????friend?class?CGraphConfiguration;
????HINSTANCE?m_hinstLib;
};??????? 當(dāng)然,看上去本部分介紹的兩塊內(nèi)容似乎關(guān)系不大,那么在接下去的幾篇隨筆里面將會對配置文件和具體組件調(diào)用程序的銜接方法作比較詳細(xì)的說明。
posted on 2006-08-11 19:50
littlegai 閱讀(889)
評論(0) 編輯 收藏 引用 所屬分類:
我的代碼玩具