<source id="4vppl"><ins id="4vppl"></ins></source>
<u id="4vppl"><sub id="4vppl"><label id="4vppl"></label></sub></u>
<object id="4vppl"></object>
  • <u id="4vppl"><li id="4vppl"><label id="4vppl"></label></li></u>

    <object id="4vppl"></object>
    <b id="4vppl"><sub id="4vppl"><tr id="4vppl"></tr></sub></b>

      <i id="4vppl"><thead id="4vppl"></thead></i>

      <thead id="4vppl"><li id="4vppl"><label id="4vppl"></label></li></thead>

      當前位置:首頁 > 網站舊欄目 > 學習園地 > 設計軟件教程 > 深入分析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/的會員


      安徽新華電腦學校專業職業規劃師為你提供更多幫助【在線咨詢
      国产午夜福三级在线播放_亚洲精品成a人片在线观看_亚洲自慰一区二区三区_久久棈精品久久久久久噜噜
      <source id="4vppl"><ins id="4vppl"></ins></source>
      <u id="4vppl"><sub id="4vppl"><label id="4vppl"></label></sub></u>
      <object id="4vppl"></object>
    1. <u id="4vppl"><li id="4vppl"><label id="4vppl"></label></li></u>

      <object id="4vppl"></object>
      <b id="4vppl"><sub id="4vppl"><tr id="4vppl"></tr></sub></b>

        <i id="4vppl"><thead id="4vppl"></thead></i>

        <thead id="4vppl"><li id="4vppl"><label id="4vppl"></label></li></thead>
        一本色道久久88综合精品 | 久久国产香肠视频限制免费 | 亚洲产在线观看亚洲第一站 | 日韩欧美国产偷 | 久久精品国产首页国产 | 日本色道亚洲精品 |