このアーカイブは同期化されません。 mixi の日記が更新されても、このアーカイブには反映されません。
クラスオブジェクトが完成した。
これをクライアントに公開するためには、
クラスに一意のクラス ID を割り当てる必要がある。
これは、guidgen などのコマンドを使えば生成できる。
プログラム的に作成したい場合は、
CoCreateGuid API を呼び出しても取得できる。
guidgen を使った場合は、生成した ID を
C++ のソースに書ける形でクリップボードにコピーできる。
// {755525B6-51FB-490b-A21B-91F7208C9429}
static const GUID <<name>> =
{ 0x755525b6, 0x51fb, 0x490b, { 0xa2, 0x1b, 0x91, 0xf7, 0x20, 0x8c, 0x94, 0x29 } };
これをソースファイルにコピーし、
<<name>> の部分を、CLSID_HardLinkIconID に書き換えると、
すぐにコードとして利用できるようになる。
クラス ID は複数のソースから参照されるので、
ヘッダファイルに格納するのが一般的だが、
上記の場合、static const となっているので、
ソースファイル内でのみ使える定数を定義する事になる。
static がついている場合、内部リンケージとなり、
複数のソースファイルでヘッダファイルを利用した場合、
ソースファイル毎に実体が作成される。
その数だけメモリが消費されてしまうことになる。
GUID は 16 バイトなので、それほどは大きくないし、
変数ではなく定数なので実害は少ないが、
複数のソースファイルから参照されることを考えて、
実体を 1 つだけにしておきたい。
本来は、この COM サーバを使う C++ クライアントの為に、
依存性のない専用のヘッダファイルに格納すべきだが
今回は手を抜いて、global.hpp と global.cpp に入れよう。
後で分離することはそれほど難しくない。
まずは宣言を global.hpp に書く。
========== global.hpp ==========
//(…前略…)
// グローバル変数
extern HMODULE g_moduleHandle;
extern ULONG g_serverLockCount;
// グローバル定数
extern const GUID CLSID_HardLinkIconID;
#endif // !global_hpp_included
========== end of global.hpp ==========
続いて、実体を global.cpp に定義する。
========== global.cpp ==========
//(…前略…)
// グローバル変数の実体
HMODULE g_moduleHandle = NULL;
ULONG g_serverLockCount = 0;
// グローバル定数の定義(実体)
// {755525B6-51FB-490b-A21B-91F7208C9429}
extern const GUID CLSID_HardLinkIconID =
{ 0x755525b6, 0x51fb, 0x490b, { 0xa2, 0x1b, 0x91, 0xf7, 0x20, 0x8c, 0x94, 0x29 } };
========== end of global.cpp ==========
C++ ではグローバル定数を定義する場合は、
変数と違って extern の明示が必要となる。
ファイルスコープで extern も static も省略した場合は、
デフォルトのリンケージが使われるのだが、
C の既定値は定数も変数も extern であるが、
C++ では定数が static で変数が extern だからだ。
C++ には名前空間があるので、
static/extern を意識して使うことは少ないが、
C 風のコードも利用する C++ 開発の場合は、
リンケージに注意する必要がある。
今回は global.cpp も global.hpp を取り込んでおり、
global.hpp でリンケージが extern と明示されているため、
extern を省略しても外部リンケージとなるが、
定数定義だけ移動したりコピーしたりすることを考え、
extern をつけておいたほうが無難である。
上記の定義により、CLSID_HardLinkIconID を、
グローバル定数として使えるようになった。
この CLSID_HardLinkIconID は、
HardLinkIconID クラスを表す一意の ID であり、
クライアントがクラスを要求する際に利用される事になる。