GUIDは分散コンピューティング環境(DCE: distributed computing environment)におけるUUID(universally unique identifier)のマイクロソフトによる実装です。
GUID構造体GUID構造体は128ビットのGUID値を保持するために用いられます。StringFromCLSID関数を使うと、この構造体を{FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF}形式の文字列に変換することができます。
GUID構造体はSDKのGuiddef.hで以下のように定義されています。
typedef struct _GUID { unsigned long Data1; unsigned short Data2; unsigned short Data3; unsigned char Data4[ 8 ]; } GUID;
Data1 | GUIDの最初の8桁の16進数を指定します |
---|---|
Data2 | 最初の4桁の16進数のグループを指定します |
Data3 | 二番目の4桁の16進数のグループを指定します |
Data4 | 最初の2バイトには三番目の4桁の16進数のグループを指定します。残りの6バイトには最後の12桁の16進数をしてします |
A28BBADE-64B6-11D2-A231-00C04FA31809という値のGUIDをGUID構造体にセットするには、以下のようにします。
GUID guid; guid.Data1 = 0xA28BBADE; guid.Data2 = 0x11D2; guid.Data3 = 0xA231; guid.Data3 = 0x00C04FA31809;
SDKのAPIではGUIDを定義する際にDEFINE_GUIDというマクロを使っています。たとえばWIAに関するGUIDはWiaDef.hで定義されていますが、このときDEFINE_GUIDマクロが使われます。msdnではこのマクロについて詳しい説明がありません。ソース(ヘッダファイル)を調べると、DEFINE_GUIDはSKDのGuiddef.hで定義されています。
#ifdef INITGUID #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ EXTERN_C const GUID vDECLSPEC_SELECTANY name = \ { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } #else #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ EXTERN_C const GUID FAR name #endif // INITGUID
INITGUIDが定義されていないときは、つぎのように展開されます。
EXTERN_C const GUID FAR name
EXTERN_Cは「extern」または「extern "C"」に展開されますので、これは単に変数のextern宣言ということに他なりません。INITGUIDが定義されているときは、つぎのように展開されます。
EXTERN_C const GUID FAR name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
この場合はGUID型の変数の記憶領域が確保されて変数の内容がマクロで指定された値に初期化されます。externを伴う変数の初期化(または定義)がCの仕様として許容されるのか疑問ですが、(少なくとも)VC++では警告も無くビルドされます。わざわざexternまたはextern "C"をつける理由がまだ良くわかりません。INITGUIDを検索するとあちこちのソースで#defineされたり#undefされたりしています。EXTERN_Cはexternもしくは(C++時)extern "C"として定義されています。 以上の状況から、GUIDの実体(オブジェクト)が作られるソース(GUIDを宣言ではなく定義するソース)ではINITGUIDを#defineして、それ以外は#undef(またはINITGUIDを#defineしない)することでヘッダを共有できるようにしていると思われます。