仿真VC++提供的關鍵字__uuidof

這個技巧不是針對VC++缺陷的,而是針對VC++擴展語法的。這個技巧的來由,是爲了某些希望有一天有可能要脫離Visual C++環境進行開發的人員。爲了脫離VC++,你需要謹慎使用它的所有擴展語法。例如本文討論的__uuidof。我們先來看看一個例子:

  1. class __declspec(uuid("B372C9F6-1959-4650-960D-73F20CD479BA")) Class;
  2. struct __declspec(uuid("B372C9F6-1959-4650-960D-73F20CD479BB")) Interface;
  3.  
  4. void test()
  5. {
  6.    CLSID clsid = __uuidof(Class);
  7.    IID iid = __uuidof(Interface);
  8.    ...
  9. }

這 比起你以前定義uuid的方法簡單多了吧?可惜,這樣好用的東西,它只在VC++中提供。不過沒有關係,我們這裏介紹一個技巧,可以讓你在幾乎所有C++ 編譯器中都可以這樣方便的使用__uuidof。這裏沒有說是所有,是因爲我們使用了模板特化技術,可能存在一些比較“古老”的C++編譯器,不支持該特 性。
 
也許你已經迫不及待了。好,讓我們來看看:

  1. #include <string>
  2. #include <cassert>
  3.  
  4. inline
  5. STDMETHODIMP_(GUID) GUIDFromString(LPOLESTR lpsz)
  6. {
  7.     HRESULT hr;
  8.     GUID guid;
  9.     if (lpsz[0] == '{')
  10.     {
  11.         hr = CLSIDFromString(lpsz, &guid);
  12.     }
  13.     else
  14.     {
  15.         std::basic_string<OLECHAR> strGuid;
  16.         strGuid.append(1, '{');
  17.         strGuid.append(lpsz);
  18.         strGuid.append(1, '}');
  19.         hr = CLSIDFromString((LPOLESTR)strGuid.c_str(), &guid);
  20.     }
  21.     assert(hr == S_OK);
  22.     return guid;
  23. }
  24.  
  25. template <class Class>
  26. struct _UuidTraits {
  27. };
  28.  
  29. #define _DEFINE_UUID(Class, uuid)                                        /
  30. template <>                                                                       /
  31. struct _UuidTraits<Class> {                                                    /
  32.     static const GUID& Guid() {                                                /
  33.         static GUID guid = GUIDFromString(L ## uuid);                /
  34.         return guid;                                                                 /
  35.     }                                                                                    /
  36. }
  37.  
  38. #define __uuidof(Class)    _UuidTraits<Class>::Guid()
  39.  
  40. #define DEFINE_CLSID(Class, guid)                                        /
  41.     class Class;                                                                      /
  42.     _DEFINE_UUID(Class, guid)
  43.  
  44. #define DEFINE_IID(Interface, iid)                                         /
  45.     struct Interface;                                                              /
  46.     _DEFINE_UUID(Interface, iid)
  47.  

這樣一來,就已經模擬出一個__uuidof關鍵字。我們可以很方便進行uuid的定義。舉例如下:
 
  1. DEFINE_CLSID(Class, "{B372C9F6-1959-4650-960D-73F20CD479BA}");
  2. DEFINE_IID(Interface, "{B372C9F6-1959-4650-960D-73F20CD479BB}");
  3.  
  4. void test()
  5. {
  6.    CLSID clsid = __uuidof(Class);
  7.    IID iid = __uuidof(Interface);
  8.    ...
  9. }

在VC++中,爲了與其他編譯器以相同的方式來進行uuid的定義,我們不直接使用__declspec(uuid),而是也定義DEFINE_CLSID, DEFINE_IID宏:
 
  1. #define DEFINE_CLSID(Class, clsid)           /
  2.     class __declspec(uuid(clsid)) Class
  3.  
  4. #define DEFINE_IID(Interface, iid)           /
  5.     struct __declspec(uuid(iid)) Interface

這樣一來,我們已經在所有包含VC++在內的支持模板特化技術的編譯器中,提供了__uuidof關鍵字。通過它可以進一步簡化你在C++語言中實現COM組件的代價。
發佈了0 篇原創文章 · 獲贊 0 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章