青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

<2009年5月>
262728293012
3456789
10111213141516
17181920212223
24252627282930
31123456

統(tǒng)計(jì)

  • 隨筆 - 24
  • 文章 - 0
  • 評(píng)論 - 17
  • 引用 - 0

常用鏈接

留言簿(4)

隨筆分類(lèi)

隨筆檔案

相冊(cè)

搜索

  •  

最新評(píng)論

閱讀排行榜

評(píng)論排行榜

用C實(shí)現(xiàn)的一個(gè)基本COM接口IFoo(來(lái)自COM Programmer's Cookbook)——C實(shí)現(xiàn)COM接口系列2

C實(shí)現(xiàn)COM接口系列1中實(shí)現(xiàn)的com接口IFoo與使用它的客戶耦合在一起,沒(méi)有實(shí)現(xiàn)在各自分離的模塊,因此不符合模塊化編程思想。本期添加類(lèi)廠支持,以使接口的實(shí)現(xiàn)與接口的使用相分離。

---------------------------------------------------
類(lèi)廠的作用到底是什么?
將接口的實(shí)現(xiàn)與客戶使用分離開(kāi)來(lái)嗎?

不盡然。使用CoCreateInstance,客戶可以完全不必知道類(lèi)廠的存在,而創(chuàng)建組件,獲取組件實(shí)現(xiàn)的接口并使用。

即COM庫(kù)可以完全拋開(kāi)類(lèi)廠的概念,而是提供一個(gè)這樣的函數(shù)原型:
CoCreateObject(REFID rclsid,...,REFID riid,void **ppItf);
用戶在調(diào)用的時(shí)候可以對(duì)riid提供IID_Unknown或者特定于該對(duì)象的一個(gè)接口,直接獲取該對(duì)象的IUnknown或特定的接口指針。

可以看到,這正是CoCreateInstance所作的事情。

1 類(lèi)廠提供了間接創(chuàng)建類(lèi)對(duì)象的方式:用戶可以先獲取并持有類(lèi)廠接口指針,通過(guò)該指針?biāo)赶虻念?lèi)廠接口創(chuàng)建類(lèi)對(duì)象。適用于需要?jiǎng)?chuàng)建多個(gè)(或重復(fù)創(chuàng)建)類(lèi)對(duì)象的地方,減少了每次都要定位對(duì)象庫(kù)并把對(duì)象庫(kù)裝入內(nèi)存的開(kāi)銷(xiāo)。
2 類(lèi)廠提供了保證組件庫(kù)留在內(nèi)存不被卸載出去的另一種方法:類(lèi)廠接口函數(shù)LockServer。組件庫(kù)維護(hù)一個(gè)庫(kù)范圍計(jì)數(shù)器,只有該計(jì)數(shù)器為0時(shí),組件庫(kù)才允許自己被卸載出內(nèi)存。(與此相對(duì),引用計(jì)數(shù)是類(lèi)對(duì)象范圍的,通過(guò)該類(lèi)實(shí)現(xiàn)的各個(gè)接口來(lái)維護(hù)。如果一個(gè)類(lèi)對(duì)象的引用計(jì)數(shù)達(dá)到0,那么該對(duì)象占有的內(nèi)存就被釋放,該對(duì)象上的接口指針也不再有效。)
除了調(diào)用LockServer鎖定組件庫(kù)以外,當(dāng)創(chuàng)建的組件個(gè)數(shù)大于0時(shí),組件庫(kù)也不能被卸載。也可以說(shuō),調(diào)用一次LockServer()的作用相當(dāng)于創(chuàng)建了一個(gè)組件。

-----------------------------------------------------------------------
客戶一側(cè):
1 使用一個(gè)接口需要知道哪些信息?
備選:
接口IID
類(lèi)對(duì)象(類(lèi)廠)CLSID(或ProgID)
接口函數(shù)原型(參數(shù)個(gè)數(shù),類(lèi)型,返回值)
實(shí)現(xiàn)接口組件的線程模型(進(jìn)程內(nèi)、進(jìn)程外、遠(yuǎn)程)?
類(lèi)型庫(kù)typelib信息?

服務(wù)一側(cè):
2 實(shí)現(xiàn)一個(gè)組件和接口以供客戶調(diào)用,需要提供哪些東西?
備選:
所有客戶使用組件和接口所需的內(nèi)容
額外的還有:


--------------------------------------------------------------------
為dll添加.def文件與直接在需要導(dǎo)出的函數(shù)定義處指定_declspec( dllexport )有區(qū)別嗎?如果有是什么區(qū)別?

我發(fā)現(xiàn)在outdll.c中這樣指定:
__declspec( dllexport ) HRESULT DllGetClassObject (REFCLSID rclsid, REFIID riid, void **ppv)
會(huì)產(chǎn)生編譯錯(cuò)誤:
1>------ Build started: Project: outside, Configuration: Debug Win32 ------
1>Compiling...
1>outdll.c
1>d:\outside-cf\outside\outdll.c(19) : error C2375: 'DllGetClassObject' : redefinition; different linkage
1>        c:\program files\microsoft visual studio 8\vc\platformsdk\include\objbase.h(833) : see declaration of 'DllGetClassObject'
1>Build log was saved at "file://d:\outside-cf\outside\Debug\BuildLog.htm"
1>outside - 1 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 1 up-to-date, 0 skipped ==========

c2375的解釋意思是出錯(cuò)的函數(shù)使用的鏈接指示符與之前聲明的不同。
Compiler Error C2375
'function' : redefinition; different linkage

The function is already declared with a different linkage specifier.

objbase.h中聲明了DllGetClassObject()函數(shù):
STDAPI  DllGetClassObject(IN REFCLSID rclsid, IN REFIID riid, OUT LPVOID FAR* ppv);

而使用.def文件就沒(méi)有問(wèn)題。

-----------------------------------------------------------------------------
初次執(zhí)行結(jié)果:

問(wèn)題就是總有一個(gè)分配的內(nèi)存沒(méi)有釋放:

 


根據(jù)打印出來(lái)的內(nèi)存地址可以判斷,應(yīng)該是先創(chuàng)建的類(lèi)廠對(duì)象的內(nèi)存沒(méi)有釋放。
檢查代碼,main()中并沒(méi)有忘記調(diào)用Release(pCF)釋放類(lèi)廠對(duì)象。打印Release(pCF)的返回值,發(fā)現(xiàn)是1,即在類(lèi)廠接口指針上少調(diào)用了一次Release,那么,究竟是哪里少的呢?

main()函數(shù)中有關(guān)類(lèi)廠對(duì)象引用計(jì)數(shù)的地方就是CoGetClassObject和Release(CreateInstance跟類(lèi)廠自己的引用計(jì)數(shù)無(wú)關(guān)),這是一對(duì)增加引用計(jì)數(shù)和減少引用計(jì)數(shù)的對(duì)應(yīng)操作,所以,main()中應(yīng)該沒(méi)有問(wèn)題。

那么,就只有創(chuàng)建類(lèi)廠對(duì)象的時(shí)候了。下面看一下類(lèi)廠對(duì)象是如何創(chuàng)建的。
首先,main調(diào)用CoGetClassObject,該函數(shù)就調(diào)用dll中的DllGetClassObject。由于是第一次調(diào)用(不考慮其他客戶使用該dll的情況),程序執(zhí)行到CreateClassFactory(...),該函數(shù)執(zhí)行完后,類(lèi)廠對(duì)象的引用計(jì)數(shù)是1。

由于創(chuàng)建成功,因此繼續(xù)向下執(zhí)行到QueryInterface,此時(shí),類(lèi)廠對(duì)象的引用計(jì)數(shù)變成了2。然后,DllGetClassObject返回,com庫(kù)函數(shù)CoGetClassObject也應(yīng)該返回。注意,此時(shí)的類(lèi)廠對(duì)象引用計(jì)數(shù)已經(jīng)是2了!

因此,問(wèn)題就出在這里。main調(diào)用一次CoGetClassObject后,類(lèi)廠對(duì)象的引用計(jì)數(shù)是2,而不是我想向中的1。于是,后面調(diào)用一次Release也就當(dāng)然無(wú)法釋放掉類(lèi)場(chǎng)對(duì)象了。

 

 

 1 HRESULT DllGetClassObject (REFCLSID rclsid, REFIID riid, void **ppv)
 2 {
 3     *ppv = 0;
 4     if (IsEqualCLSID (rclsid, &CLSID_Outside))
 5     {
 6 
 7         if (!vpcfOutside)
 8 
 9         {
10 
11             HRESULT hr = CreateClassFactory (&CLSID_Outside, CreateOutside,
12                                              &IID_IClassFactory, &vpcfOutside);
13 
14                 if (hr != NOERROR)
15 
16                     return hr;
17         }
18 
19         return QueryInterface (vpcfOutside, riid, ppv);
20 
21     }
22 
23     return E_FAIL;
24 }

 

 


找到了原因,改正就很容易了。這里我覺(jué)得需要把DllGetClassObject作如下修改:

 1 HRESULT DllGetClassObject (REFCLSID rclsid, REFIID riid, void **ppv)
 2 {
 3     *ppv = 0;
 4     if (IsEqualCLSID (rclsid, &CLSID_Outside))
 5     {
 6 
 7         if (!vpcfOutside)
 8 
 9         {
10 
11             HRESULT hr = CreateClassFactory (&CLSID_Outside, CreateOutside,
12                                              &IID_IClassFactory, &vpcfOutside);
13 
14                 if (hr != NOERROR)
15 
16                     return hr;
17 
18     if(IsEqualIID(riid,&IID_IClassFactory))
19     {
20      *ppv = vpcfOutside;// Set *ppv to vpcfOutside directly instead of QueryInterface if first time creation
21      return NOERROR;
22     }
23     else
24     {
25      Release(vpcfOutside);// Any interface requested (riid) other than IID_ClassFactory and IID_Unknown not support by class factory,
26                           // call Release to free the memory.
27      return E_FAIL;
28     }
29 
30         }
31 
32         return QueryInterface (vpcfOutside, riid, ppv);
33 
34     }
35 
36     return E_FAIL;
37 }

 

修改后在執(zhí)行,內(nèi)存都正常釋放了。

-------------------------------------------------------------------------------------------
CreateClassFactory代碼說(shuō)明

 1 HRESULT CreateClassFactory (REFCLSID rclsid,
 2     HRESULT (*pfnCreate)(IUnknown *, REFIID, void **), 
 3     REFIID riid, void **ppv)
 4 {
 5     ClassFactory *this;
 6     HRESULT hr;
 7     
 8     *ppv = 0;
 9     if (hr = Alloc (sizeof (ClassFactory), &this))
10     return hr;
11 
12     this->icf.lpVtbl = &vtblClassFactory;
13     this->cRef = 1;  // After this call, cRef==1
14 
15     this->pfnCreate = pfnCreate;
16     
17     hr = QueryInterface (&this->icf, riid, ppv);  // After this call, cRef==2
18     Release (&this->icf);  // Corresponds to "this->cRef = 1", ater this call, cRef==1
19 
20     return hr;
21 }

 

可以看到,兩行代碼的效果是對(duì)引用計(jì)數(shù)增1及減1,這兩行代碼執(zhí)行后,對(duì)引用計(jì)數(shù)的影響互相抵消,等于沒(méi)有改變引用計(jì)數(shù)。那么,把這兩行同時(shí)注釋掉,是不是可以呢?
我的回答是:在本例中可以。因?yàn)檫@兩行代碼之間的QueryInterface總是可以執(zhí)行成功的(因?yàn)槭怯肐DD_ClassFactory來(lái)調(diào)用該函數(shù)的)。所以,即便把這兩行代碼同時(shí)注釋掉,CreateClassFactory執(zhí)行結(jié)束后,類(lèi)廠對(duì)象的引用計(jì)數(shù)也增了1,以后調(diào)用Release就可以釋放掉類(lèi)廠對(duì)象占用的內(nèi)存。
但是,如果CFQueryInterface的代碼編寫(xiě)中除了錯(cuò)誤,比如,像這樣寫(xiě):

 1 static HRESULT CFQueryInterface (IClassFactory *pcf, REFIID riid, void **ppv)
 2 {
 3     ClassFactory *this = IMPL (ClassFactory, icf, pcf);
 4 
 5     if (IsEqualIID (riid, &IID_IUnknown) ||
 6 //            IsEqualIID (riid, &IID_IClassFactory))   // Comment out this condition to create an error
 7         *ppv = &this->icf;
 8     else
 9     {
10         *ppv = 0;
11         return E_NOINTERFACE;
12     }
13 
14     AddRef ((IClassFactory *)*ppv);
15 
16     return NOERROR;
17 }


那么,這兩行代碼之間的QueryInterface就會(huì)執(zhí)行出錯(cuò),那么類(lèi)廠對(duì)象占用的內(nèi)存就永遠(yuǎn)沒(méi)有機(jī)會(huì)釋放了。
也就是說(shuō),AddRef和Release雖然在作用上對(duì)引用計(jì)數(shù)來(lái)說(shuō)相互抵消,但Release函數(shù)提供了釋放對(duì)象內(nèi)存的機(jī)會(huì)(當(dāng)引用計(jì)數(shù)為0時(shí)),如果不成對(duì)的調(diào)用他們,也就失去了管理對(duì)象內(nèi)存(釋放對(duì)象占用的內(nèi)存)的機(jī)會(huì)。

---------------------------------------------------------------------------
組件庫(kù)outside文件說(shuō)明:
 IFoo.h      IFoo接口聲明
 outside.c   組件對(duì)象、IFoo接口實(shí)現(xiàn)
 cf.c        類(lèi)廠對(duì)象、IClassFactory接口實(shí)現(xiàn)
 outdll.c    組件庫(kù)導(dǎo)出函數(shù)實(shí)現(xiàn)
 outside.def 組件庫(kù)模塊定義文件,導(dǎo)出函數(shù)聲明
 outside.reg 組件庫(kù)注冊(cè)文件

----------------------------------------------------------------------------
源碼: outside-cf

posted on 2009-05-11 16:28 小蔥蘸醬 閱讀(1164) 評(píng)論(0)  編輯 收藏 引用 所屬分類(lèi): 編碼點(diǎn)滴

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美三级欧美一级| 午夜精品久久99蜜桃的功能介绍| 午夜精品免费在线| 午夜欧美不卡精品aaaaa| 好吊色欧美一区二区三区四区 | 欧美日韩国产三区| 久久成人国产| 欧美国产视频在线| 久久精品国产成人| 欧美日韩国产精品专区| 久久青青草综合| 欧美日韩免费观看一区二区三区| 久久久综合免费视频| 欧美日韩一区在线观看视频| 久久综合激情| 国产精品美女www爽爽爽视频| 欧美不卡视频一区发布| 国产欧美欧洲在线观看| 日韩视频在线一区二区| 亚洲第一久久影院| 欧美一区二区视频免费观看| 国产精品99久久久久久人| 免费观看成人网| 久久人人爽国产| 国产日韩在线亚洲字幕中文| 妖精视频成人观看www| 亚洲国产精品va| 欧美一级精品大片| 欧美私人啪啪vps| 亚洲人成网站在线观看播放| 国产精品高潮视频| 亚洲人成免费| 亚洲精品乱码久久久久久黑人 | 亚洲欧美日韩国产综合| 免费视频一区| 欧美v日韩v国产v| 国内自拍视频一区二区三区| 亚洲专区国产精品| 亚洲主播在线播放| 国产精品国产三级国产aⅴ浪潮| 亚洲激情视频| 亚洲国产精品va在线看黑人| 欧美主播一区二区三区| 久久精品色图| 国产主播一区| 久久久久国产一区二区三区四区 | 国产精品久久久久久久午夜| 夜夜嗨av一区二区三区免费区| 亚洲欧洲视频| 欧美精品xxxxbbbb| 亚洲精品视频在线播放| 一本色道久久综合狠狠躁篇怎么玩 | 国产色爱av资源综合区| 亚洲永久免费观看| 欧美在线一区二区| 国产一区清纯| 久久一区二区三区国产精品| 免费久久99精品国产自| 亚洲第一主播视频| 欧美国产高清| 一区二区高清视频| 香蕉尹人综合在线观看| 国产日韩欧美一区二区三区在线观看 | 国产精品入口福利| 亚洲欧美色一区| 久久久久88色偷偷免费| 激情亚洲网站| 欧美刺激午夜性久久久久久久| 亚洲精品乱码视频| 亚洲欧美日本国产有色| 国产在线观看精品一区二区三区 | 欧美一区三区二区在线观看| 国产视频久久网| 快she精品国产999| 日韩视频一区| 久久精品亚洲热| 91久久嫩草影院一区二区| 欧美三级免费| 久久久久久国产精品一区| 亚洲激情在线播放| 国模精品一区二区三区| 久久亚洲精品网站| 99国产精品久久久久久久久久| 香蕉久久精品日日躁夜夜躁| 一区久久精品| 国产精品video| 久久美女艺术照精彩视频福利播放| 亚洲国产精品欧美一二99| 亚洲小说欧美另类社区| 好吊色欧美一区二区三区四区| 欧美激情国产日韩精品一区18| 亚洲一区二区3| 欧美激情欧美激情在线五月| 午夜国产精品视频| 亚洲国产高清一区二区三区| 国产精品久久久久久久午夜片| 久久精品亚洲精品| 亚洲视屏一区| 亚洲激情在线观看视频免费| 久久成人精品| 亚洲午夜影视影院在线观看| 影音先锋久久| 国产九九视频一区二区三区| 欧美华人在线视频| 久久亚洲精品中文字幕冲田杏梨| 亚洲桃花岛网站| 亚洲青涩在线| 欧美高清在线视频| 久久综合导航| 久久久精品国产一区二区三区| 亚洲深夜福利在线| 亚洲精品久久久久久久久久久久| 国产亚洲成av人在线观看导航| 欧美国产精品日韩| 久久在线视频在线| 久久精品一区二区国产| 亚洲一区欧美二区| 一本色道**综合亚洲精品蜜桃冫 | 国产一区二区三区在线观看视频 | 欧美激情aaaa| 久久在线免费观看| 午夜日韩电影| 亚洲欧美日韩精品久久亚洲区| 亚洲免费福利视频| 亚洲国产日韩在线一区模特| 精品91视频| 国产真实乱偷精品视频免| 国产精品一区二区a| 欧美性生交xxxxx久久久| 欧美日韩国产精品一区| 欧美精品一区二区在线观看 | 麻豆av一区二区三区久久| 欧美在线视频在线播放完整版免费观看 | 亚洲作爱视频| 日韩视频在线免费| 亚洲美女精品成人在线视频| 亚洲国产婷婷香蕉久久久久久| 欧美成人综合在线| 亚洲第一久久影院| 最新国产の精品合集bt伙计| 国产精品免费在线| 免费看精品久久片| 午夜精品视频一区| 性久久久久久久| 欧美一级艳片视频免费观看| 篠田优中文在线播放第一区| 午夜在线一区| 久久精品视频在线播放| 久久久久久免费| 欧美a一区二区| 欧美日韩国产电影| 欧美视频在线观看视频极品| 欧美午夜免费影院| 国产美女高潮久久白浆| 激情伊人五月天久久综合| 亚洲激情另类| 亚洲一级在线| 久久精品国产99精品国产亚洲性色 | 久久国产免费看| 久久国产加勒比精品无码| 久久婷婷亚洲| 欧美丰满高潮xxxx喷水动漫| 欧美色精品在线视频| 国产色综合网| 99精品久久久| 久久岛国电影| 亚洲国产精品精华液2区45| 在线亚洲美日韩| 久久精品男女| 欧美日韩午夜剧场| 国产一区二区三区久久悠悠色av| 亚洲韩国一区二区三区| 亚洲影院色在线观看免费| 久久久人人人| 亚洲精品中文在线| 久久精品日产第一区二区| 欧美日韩国语| 一区三区视频| 亚洲综合久久久久| 欧美不卡在线视频| 亚洲视频观看| 你懂的视频欧美| 国产精品一区二区欧美| 91久久综合亚洲鲁鲁五月天| 午夜精品久久久| 91久久久久久| 久久精品日产第一区二区| 欧美午夜精品| 亚洲国产你懂的| 欧美在线高清| 日韩亚洲欧美成人一区| 久久阴道视频| 国产日韩欧美制服另类| 一区二区三区欧美视频| 久久婷婷激情| 亚洲一区二区视频在线| 欧美wwwwww| 一区视频在线看| 久久黄色影院| 亚洲午夜女主播在线直播|