3)仿真VC++提供的關鍵字__uuidof。
我們先來看看一個例子:
class __declspec(uuid("B372C9F6-1959-4650-960D-73F20CD479BA")) Class;
struct __declspec(uuid("B372C9F6-1959-4650-960D-73F20CD479BB")) Interface;
void test()
{
CLSID clsid = __uuidof(Class);
IID iid = __uuidof(Interface);
...
}
這比起你以前定義uuid的方法簡單多了吧?可惜,這樣好用的東西,它只在VC++中提供。不過沒有關係,我們這裡介紹一個技巧,可以讓你在幾乎所有C++編譯器中都可以這樣方便的使用__uuidof。這裡沒有說是所有,是因為我們使用了模板特化技術,可能存在一些比較“古老”的C++編譯器,不支持該特性。
也許你已經迫不及待了。好,讓我們來看看:
#include <string>
#include <cassert>
inline
STDMETHODIMP_(GUID) GUIDFromString(LPOLESTR lpsz)
{
HRESULT hr;
GUID guid;
if (lpsz[0] == '{')
{
hr = CLSIDFromString(lpsz, &guid);
}
else
{
std::basic_string<OLECHAR> strGuid;
strGuid.append(1, '{');
strGuid.append(lpsz);
strGuid.append(1, '}');
hr = CLSIDFromString((LPOLESTR)strGuid.c_str(), &guid);
}
assert(hr == S_OK);
return guid;
}
template <class Class>
struct _UuidTraits {
};
#define _DEFINE_UUID(Class, uuid) \
template <> \
struct _UuidTraits<Class> { \
static const GUID& Guid() { \
static GUID guid = GUIDFromString(L ## uuid); \
return guid; \
} \
}
#define __uuidof(Class) _UuidTraits<Class>::Guid()
#define DEFINE_CLSID(Class, guid) \
class Class; \
_DEFINE_UUID(Class, guid)
#define DEFINE_IID(Interface, iid) \
struct Interface; \
_DEFINE_UUID(Interface, iid)
這樣一來,就已經模擬出一個__uuidof關鍵字。我們可以很方便進行uuid的定義。舉例如下:
DEFINE_CLSID(Class, "{B372C9F6-1959-4650-960D-73F20CD479BA}");
DEFINE_IID(Interface, "{B372C9F6-1959-4650-960D-73F20CD479BB}");
void test()
{
CLSID clsid = __uuidof(Class);
IID iid = __uuidof(Interface);
...
}
在VC++中,為了與其他編譯器以相同的方式來進行uuid的定義,我們不直接使用__declspec(uuid),而是也定義DEFINE_CLSID, DEFINE_IID宏:
#define DEFINE_CLSID(Class, clsid) \
class __declspec(uuid(clsid)) Class
#define DEFINE_IID(Interface, iid) \
struct __declspec(uuid(iid)) Interface
這樣一來,我們已經在所有包含VC++在內的支持模板特化技術的編譯器中,提供了__uuidof關鍵字。通過它可以進一步簡化你在C++語言中實現COM組件的代價。
附註:關於本文使用的C++模板的特化技術,詳細請參閱C++文法方面的書籍,例如《C++ Primer》。其實這個技巧在C++標準庫――STL中有一個專門的名字:traits(萃取),你可以在很多介紹STL的書籍中見到相關的介紹。
to be continued ...
-----
ps:用處不大,要是能夠獲取標準的接口id就好了。
__uuidof關鍵字用來獲得表達式的GUID。這個表達式可以是一種類型,名稱、一個指針‘引用或者一個類型的數組、一個有這個類型實例化的模板或者這種類型的變數。只要編譯器能使該參數獲得相關的GUID,那么該參數就是有效的。一個特殊案件,這是內在時,無論是零或null是供應作為論據。在這種情況下, __uuidof將返回一個GUID ,彌補了零點。
注意:
在調試建設, __uuidof始終初始化一個對象動態(在運行時),
在釋放建設, __uuidof可以靜態(在編譯時)初始化一個對象。
GUID(全國統一的標識符)是指在一台機器上生成的數字,他保證對在同一時空中的所有機器都是唯一的。
1.一個GUID為一個128位的整數(16位元組),在使用唯一標識符的情況下,你可以在所有計算機和網路之間使用這一整數。
2.GUID的格式為“xxxxXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX”,每個x是0-9或A-F範圍內的一個十六進制的數字。
3.世間上的任何兩台計算機都不會生成重複的GUID值。GUID主要用在擁有多個節點、多台計算機的網路或系統中,分配必須具有唯一性的標識符。
4.在Windows平台上,GUID套用非常廣泛:註冊表、類及接口標示、資料庫、甚至自動生成的機器名、目錄名。
1、在 SQL Server 中使用 GUID
如果在 SQL Server 的表定義中將列類型指定為 uniqueidentifier,則列的值就為 GUID 類型。
SQL Server 中的 NewID() 函式可以產生 GUID 唯一值,使用此函式的幾種方式如下:
1) 作為列默認值
將 uniqueidentifier 的列的默認值設為 NewID(),這樣當新行插入表中時,會自動生成此列 GUID 值。
2)使用 T-SQL
在 T-SQL 中使用 NewID()函式,如“INSERT INTO Table(ID,... ) VALUES(NewID(),...)”來生成此列的 GUID 值