亚洲人成网站在线播放2019 _日韩国产欧美精品_久久夜色精品国产欧美乱_在线视频福利一区

當前位置:首頁 > 網站舊欄目 > 學習園地 > 設計軟件教程 > 深入分析D語言接口與COM接口的關系

深入分析D語言接口與COM接口的關系
2010-01-13 21:04:58  作者:佚名  來源:


深入分析D語言接口與COM接口的關系
   
    前兩天為了解決dxpcom項目中遇到的xpcom接口兼容性問題,看了一下DMD編譯器的源碼,對D的接口有了一些了解,現在總結出來,備忘。

    D中有了專門用于標識接口的關鍵字interface,而不用象C++中使用抽象類來代替。
    D代碼:
Java代碼
interface ITest  
{  
int test();  

interface ITest
{
int test();
}
    C++代碼:
Java代碼
class ITest  
{  
int test()=0;  

class ITest
{
int test()=0;
}

    而D中的接口與C++中的接口不同之處是,D中的接口仍然含有ClassInfo,存放在虛表的0項上。

    從DMD的源碼中可以得知,D中的類,接口都在虛表的0項上保存了ClassInfo指針。
    這樣,D中的接口是無法與C++接口兼容的,則D就無法調用Windows的COM對象,至少是無法“優雅”的調用(仍然可以使用struct進行二進制兼容代替)。

    為了解決這個問題,DMD就需要能夠表示出與C++兼容的COM接口,即需要一個虛表是"干凈"的接口。又由于,從一個COM接口繼承的接口仍然是一個COM接口,而COM模型的實現上又恰好定義了一個“IUnknown”根接口(COM體系中的所有的接口都是繼承了IUnknown)。

    所以,出于簡單實現的原則,DMD區分一個接口是D接口還是COM接口,關鍵就是判斷這個接口是不是叫做IUnknown,以及這個接口是否繼承自IUnknown,雖然接口都是通過Interface關鍵字聲明。更有趣的是,DMD僅僅判斷接口的名字是否為"IUnknown"而根本不管接口中的方法如何定義。

    以上所述內容在進行Windows COM編程時,幾乎不會被察覺,因為Windows的所有接口都是繼承自IUnknown,只要正常使用就可以了。

    而在進行Mozilla xpcom編程的時候,xpcom的根接口叫做ISupports,DMD根本就不會認為這是需要編譯為C++兼容的COM接口,而仍然會將虛表的0項進行保留,結果給使用者造成了虛表指針偏移了的印象。

    基于D的這個識別COM接口的方式,在dxpcom項目中,qiezi使用了別名的方式進行了變換,既將dxpcom項目中的所有的接口名稱進行了優雅的統一,又能夠使DMD生成正確的COM接口:
Java代碼
extern(Windows)  
interface IUnknown {  
  static const char[] IID_STR = NS_ISUPPORTS_IID_STR;  
  static const nsIID IID = NS_ISUPPORTS_IID;  
 
  /* void QueryInterface (in nsIIDRef uuid, [iid_is (uuid), retval] out nsQIResult result); */ 
  nsresult QueryInterface(nsIID * uuid, void * *result);  
 
  /* [noscript, notxpcom] nsrefcnt AddRef (); */ 
  nsrefcnt AddRef();  
 
  /* [noscript, notxpcom] nsrefcnt Release (); */ 
  nsrefcnt Release();  
 
}  
 
alias IUnknown nsISupports; 

extern(Windows)
interface IUnknown {
  static const char[] IID_STR = NS_ISUPPORTS_IID_STR;
  static const nsIID IID = NS_ISUPPORTS_IID;

  /* void QueryInterface (in nsIIDRef uuid, [iid_is (uuid), retval] out nsQIResult result); */
  nsresult QueryInterface(nsIID * uuid, void * *result);

  /* [noscript, notxpcom] nsrefcnt AddRef (); */
  nsrefcnt AddRef();

  /* [noscript, notxpcom] nsrefcnt Release (); */
  nsrefcnt Release();

}

alias IUnknown nsISupports;

   這個現象同時也很好的說明了,D中的別名(alias)在符號的處理方面僅僅是一個符號的替換,同C/C++中的#define的作用相同。

    下面的兩段代碼就能很好的詮釋本文的內容(感謝qiezi提供)

    代碼一,無法通過運行期斷言,因為接口IInterface仍然為標準D接口,虛表的0項為ClassInfo指針無法被顯示的調用,在執行的結果中就表現為虛表進行了偏移。
Java代碼
extern(Windows):     
int test1(IInterface p)     
{     
    return 1;     
}     
    
int test2(IInterface p)     
{     
    return 2;     
}     
    
int test3(IInterface p)     
{     
    return 3;     
}     
    
struct InterfaceVtbl     
{     
extern(Windows):     
    int function(IInterface) test1;     
    int function(IInterface) test2;     
    int function(IInterface) test3;     
}     
    
struct Interface     
{     
    InterfaceVtbl* vtbl;     
    
    InterfaceVtbl vtbl_;     
    
    static Interface opCall()     
    {     
        Interface res;     
        res.vtbl_.test1 = &test1;     
        res.vtbl_.test2 = &test2;     
        res.vtbl_.test3 = &test3;     
        res.vtbl = &res.vtbl_;     
        return res;     
    }     
}     
    
interface IInterface     
{     
    int test1();     
    int test2();     
    int test3();     
}     
    
extern (D):     
    
void main()     
{     
    Interface i = Interface();     
    assert(i.vtbl.test1(cast(IInterface)&i) == 1);     
    assert(i.vtbl.test2(cast(IInterface)&i) == 2);     
    assert(i.vtbl.test3(cast(IInterface)&i) == 3);     
    
    IInterface ii = cast(IInterface)&i;     
    assert(ii.test1() == 1);     
    assert(ii.test2() == 2);     
    assert(ii.test3() == 3);     

extern(Windows):  
int test1(IInterface p)  
{  
    return 1;  
}  
 
int test2(IInterface p)  
{  
    return 2;  
}  
 
int test3(IInterface p)  
{  
    return 3;  
}  
 
struct InterfaceVtbl  
{  
extern(Windows):  
    int function(IInterface) test1;  
    int function(IInterface) test2;  
    int function(IInterface) test3;  
}  
 
struct Interface  
{  
    InterfaceVtbl* vtbl;  
 
    InterfaceVtbl vtbl_;  
 
    static Interface opCall()  
    {  
        Interface res;  
        res.vtbl_.test1 = &test1;  
        res.vtbl_.test2 = &test2;  
        res.vtbl_.test3 = &test3;  
        res.vtbl = &res.vtbl_;  
        return res;  
    }  
}  
 
interface IInterface  
{  
    int test1();  
    int test2();  
    int test3();  
}  
 
extern (D):  
 
void main()  
{  
    Interface i = Interface();  
    assert(i.vtbl.test1(cast(IInterface)&i) == 1);  
    assert(i.vtbl.test2(cast(IInterface)&i) == 2);  
    assert(i.vtbl.test3(cast(IInterface)&i) == 3);  
 
    IInterface ii = cast(IInterface)&i;  
    assert(ii.test1() == 1);  
    assert(ii.test2() == 2);  
    assert(ii.test3() == 3);  
}

    代碼二,與代碼一的結構完全一致,卻能夠通過運行時斷言的檢查。唯一的不同僅僅是IInterface的名字換成了IUnknown!!
Java代碼
extern(Windows):     
int test1(IUnknown p)     
{     
    return 1;     
}     
    
int test2(IUnknown p)     
{     
    return 2;     
}     
    
int test3(IUnknown p)     
{     
    return 3;     
}     
    
struct InterfaceVtbl     
{     
extern(Windows):     
    int function(IUnknown) test1;     
    int function(IUnknown) test2;     
    int function(IUnknown) test3;     
}     
    
struct Interface     
{     
    InterfaceVtbl* vtbl;     
    
    InterfaceVtbl vtbl_;     
    
    static Interface opCall()     
    {     
        Interface res;     
        res.vtbl_.test1 = &test1;     
        res.vtbl_.test2 = &test2;     
        res.vtbl_.test3 = &test3;     
        res.vtbl = &res.vtbl_;     
        return res;     
    }     
}     
    
interface IUnknown     
{     
    int test1();     
    int test2();     
    int test3();     
}     
    
extern (D):     
    
void main()     
{     
    Interface i = Interface();     
    assert(i.vtbl.test1(cast(IUnknown)&i) == 1);     
    assert(i.vtbl.test2(cast(IUnknown)&i) == 2);     
    assert(i.vtbl.test3(cast(IUnknown)&i) == 3);     
    
    IUnknown ii = cast(IUnknown)&i;     
    assert(ii.test1() == 1);     
    assert(ii.test2() == 2);     
    assert(ii.test3() == 3);     

extern(Windows):  
int test1(IUnknown p)  
{  
    return 1;  
}  
 
int test2(IUnknown p)  
{  
    return 2;  
}  
 
int test3(IUnknown p)  
{  
    return 3;  
}  
 
struct InterfaceVtbl  
{  
extern(Windows):  
    int function(IUnknown) test1;  
    int function(IUnknown) test2;  
    int function(IUnknown) test3;  
}  
 
struct Interface  
{  
    InterfaceVtbl* vtbl;  
 
    InterfaceVtbl vtbl_;  
 
    static Interface opCall()  
    {  
        Interface res;  
        res.vtbl_.test1 = &test1;  
        res.vtbl_.test2 = &test2;  
        res.vtbl_.test3 = &test3;  
        res.vtbl = &res.vtbl_;  
        return res;  
    }  
}  
 
interface IUnknown  
{  
    int test1();  
    int test2();  
    int test3();  
}  
 
extern (D):  
 
void main()  
{  
    Interface i = Interface();  
    assert(i.vtbl.test1(cast(IUnknown)&i) == 1);  
    assert(i.vtbl.test2(cast(IUnknown)&i) == 2);  
    assert(i.vtbl.test3(cast(IUnknown)&i) == 3);  
 
    IUnknown ii = cast(IUnknown)&i;  
    assert(ii.test1() == 1);  
    assert(ii.test2() == 2);  
    assert(ii.test3() == 3);  
}

    另外需要說明的是extern(D),extern(Windows),extern(Pascal)等特征,只是用來描述函數的調用約定,與接口的類型無關。
    一句話:D中的類與標準D接口都有ClassInfo在虛表的0項上,而COM接口的虛表是干凈的;而將一個接口聲明為COM接口的方式為:將這個接口命名為IUnknown或繼承自IUnknown。

 
更多信息請登陸http://61.191.27.74:802/ 最后,歡迎加入http://61.191.27.74:802/的會員


安徽新華電腦學校專業職業規劃師為你提供更多幫助【在線咨詢
亚洲人成网站在线播放2019 _日韩国产欧美精品_久久夜色精品国产欧美乱_在线视频福利一区
男女猛烈激情xx00免费视频| 久久久精品网站| 欧洲亚洲一区二区三区四区五区| 亚洲一二三区精品| 这里只有精品66| 精品国产日本| 中文字幕久久一区| 一级日韩一区在线观看| 在线视频不卡一区二区三区| 在线播放 亚洲| 在线观看福利一区| 午夜精品蜜臀一区二区三区免费| 精品自在线视频| 一区二区三区四区免费视频| 亚洲一区二区三区精品视频| 欧美一级视频免费在线观看| 日韩久久一级片| 国产中文一区二区| 成人精品视频在线| 久久噜噜噜精品国产亚洲综合| 久久精品综合一区| 久久天天躁狠狠躁夜夜躁| 欧美成年人视频网站欧美| 久久久久久高潮国产精品视| 亚洲成人精品电影在线观看| 日本乱人伦a精品| 国内一区二区三区在线视频| 国产小视频免费| 成人av免费看| 久久99热只有频精品91密拍| 国产精品久久久久久久乖乖| 中文字幕日韩一区二区三区 | 91免费看蜜桃| 九色自拍视频在线观看| 久久精品欧美视频| 夜夜添无码一区二区三区| 日本一区免费看| 国产伊人精品在线| 99久久精品无码一区二区毛片| 久久久国产精品一区二区三区| 国产精品视频免费一区| 中文字幕免费高| 日韩精品电影网站| 成人久久久久久| 久久精品国产v日韩v亚洲| 九九久久国产精品| 日韩精品一区二区三区外面| 国产一区二区片| 久久国产一区| 中文字幕中文字幕在线中心一区| 青春草在线视频免费观看| 国产免费一区二区三区在线观看| 久久九九视频| 久久成人在线视频| 日本精品国语自产拍在线观看| 国产又爽又黄的激情精品视频| 国产激情久久久| 一区二区视频在线播放| 黄页网站在线观看视频| 久久综合亚洲精品| 宅男av一区二区三区| 黄色一级大片在线观看| 国产福利视频一区二区| 伊人久久大香线蕉综合75| 妓院一钑片免看黄大片| 国产福利精品视频| 亚洲国产精品日韩| 国产精品一区久久| 国产精品免费视频xxxx| 日本乱人伦a精品| 91看片淫黄大片91| 精品国产乱码久久久久久108| 欧美精品一区二区三区久久| 久久99国产精品99久久| 春色成人在线视频| 91精品国产成人| 一区二区三区不卡在线| 国产日韩欧美二区| 国产精品高潮视频| 狠狠爱一区二区三区| 久久久黄色av| 欧美人成在线观看| 国产精品嫩草影院久久久| 日韩免费av一区二区三区| 久久免费视频这里只有精品| 亚洲成人精品电影在线观看| 97激碰免费视频| 亚洲精蜜桃久在线| 久热免费在线观看| 日产精品久久久一区二区 | 日韩在线欧美在线国产在线| 日韩电影天堂视频一区二区| 国产v片免费观看| 日韩av在线一区二区三区| 久久综合久久久| 日韩欧美视频第二区| 久久久999视频| 奇米影视亚洲狠狠色| www国产91| 国内自拍欧美激情| 精品久久久久久乱码天堂| 高清欧美精品xxxxx| 亚洲一区二区三区四区中文| 国产精品8888| 欧美尤物巨大精品爽| 国产精品美女av| 国产伦精品一区二区三区照片91| 中文字幕免费在线不卡| 国产精品aaaa| 欧美在线观看网址综合| 超碰日本道色综合久久综合| 国产又黄又爽免费视频| 亚洲最大福利网| 久久久中精品2020中文| 欧美综合激情| 欧美成人亚洲成人| 9191国产视频| 欧美视频在线观看视频| 九九精品在线播放| 97国产在线播放| 欧洲精品久久久| 欧美日韩成人网| 国产黄色一级网站| 精品一区二区三区视频日产| 亚洲国产精品视频一区| 久久国内精品一国内精品| 国产日韩亚洲欧美在线| 亚洲欧美久久234| 国产精品视频免费在线| 97久久国产亚洲精品超碰热| 欧洲精品在线视频| 亚洲专区国产精品| www国产精品com| 99久久激情视频| 黄黄视频在线观看| 日韩在线国产| 精品国产一区三区| 久久国产精品精品国产色婷婷| 国产制服91一区二区三区制服| 婷婷久久青草热一区二区| 国产精品久久av| 久久综合入口| 国产欧美日韩精品专区| 欧洲久久久久久| 亚洲a成v人在线观看| 国产精品人人做人人爽| 久久久一二三四| 国产免费人做人爱午夜视频| 欧日韩一区二区三区| 亚洲**2019国产| 米奇精品一区二区三区在线观看| 久久久久免费精品| 91久久国产综合久久91精品网站| 黄频视频在线观看| 日韩理论片在线观看| 亚洲精品欧洲精品| 国产精品久久久久一区二区| 久久久久99精品成人片| 国产精品亚洲精品| 国内精品**久久毛片app| 日本一区二区在线视频| 亚洲欧洲久久| 欧美激情一区二区三区久久久| 国产精品免费久久久| 久久久久一区二区| 91精品国产综合久久香蕉 | 777国产偷窥盗摄精品视频| 国产日韩欧美电影在线观看| 欧美精品一区二区三区三州| 三级三级久久三级久久18| 欧美激情网站在线观看| 国产精品国产精品国产专区不卡 | 色妞色视频一区二区三区四区| 91精品天堂| 99国精产品一二二线| 国产日韩综合一区二区性色av| 青青在线视频一区二区三区| 日韩欧美99| 欧美综合在线观看| 青青青在线播放| 人妻无码视频一区二区三区| 日韩精品福利片午夜免费观看| 日韩av一区二区三区在线| 日日噜噜夜夜狠狠久久丁香五月| 一本久道高清无码视频| 一本—道久久a久久精品蜜桃| 真实国产乱子伦对白视频| 一区二区三区日韩视频| 亚洲一区在线免费| 亚洲免费av网| 亚欧洲精品在线视频免费观看| 欧美日韩成人免费| 一区二区三区久久网| 中文字幕一区综合| 亚洲成人第一| 日本精品视频网站| 欧美性视频在线| 国产一区精品视频| www精品久久| 久久日韩精品|