2006 年 10 月 10 日 23 時 0 分

ショートカットを C 言語で読む準備


このアーカイブは同期化されません。 mixi の日記が更新されても、このアーカイブには反映されません。


では、C 言語とWINAPI を使って、
ショートカットファイルを読んでみよう
以前に、C# でショートカットを読んだが、
今日はこれの C 言語版である。

http://mixi.jp/view_diary.pl?id=166475473&owner_id=2300658

前にやったのに、また取り上げるのはちょっと嫌だが、
C# では裏で隠蔽してくれていたことを、
C 言語では全て自力で実装する必要があるため、
ちょうど良い対比となるからいいとするか。

ショートカットを扱うには COM インタフェースが必要だ。
基本的に COM はオブジェクト指向なのだが、
COM は、C 言語でも利用することができる。
COM を C++ ではなくて C で使うのは珍しいけどね。

では、ショートカットを読む関数の枠組みを作ってみよう。

C 言語には名前空間がないため、
あらゆる名前がグローバル空間に犇めき合う。
そのため、命名規則を決めておかないと、
ごちゃごちゃになる心配がある。

ここでは、Shortcut というカテゴリの、
GetTarget という役割の関数ということで、
連結して ShortcutGetTarget と命名することにする。

さて、まずは外部仕様を表すヘッダファイルを作成しよう。
ShortcutGetTarget を呼び出す側が、
関数を利用できるように取り込むファイルだ。

========== lnkfile.h ==========

/* インクルードガード */
#ifndef lnkfile_h_included
#define lnkfile_h_included

/*
* ShortcutGetTarget 関数の宣言
*/

#include <windows.h>
#include <ole2.h>

HRESULT ShortcutGetTarget(const wchar_t *fileName, wchar_t *target, unsigned int bufferSize);

#endif /* !lnkfile_h_included */

========== end of lnkfile.h ==========

まずはインクルードガードが来るが、
これはヘッダファイルの基本だ。

そして、次に最小限のヘッダを取り込んでおく。

#include <windows.h>
#include <ole2.h>

windows.h が、Windows 開発に必須のヘッダ、
そして、ole2.h が、COM 基盤に必須のヘッダである。
この 2 つは定番のファイルである。

そして、ShortcutGetTarget のプロトタイプを宣言する。

引数は、ショートカットのファイル名と、
ショートカットの指す先を格納するバッファ、
そして、バッファのサイズである。
戻り値は、HRESULT だ。これは COM のエラー型である。

COM では 基本的に、Unicode を使うので、
ShortcutGetTarget も Unicode ベースにしておく。

const は、ポインタを多用する C 言語の特徴的な構文だ。
const wchar_t * は読み取り専用 Unicode 文字列で、
wchar_t * は、読み書き可能な Unicode 文字列である。

個人的に、Java や C# にも引数の const 指定が欲しい。
不変型でないクラスをメソッドに渡しても、
メソッド内で値を変更しないことを保証したいことがある。
(setter を呼び出すとコンパイルエラーとかって助かるんだが…)

さて、次に、実装ファイルを作成しよう。

========== lnkfile.c ==========

/* 制御マクロ宣言 */

#define UNICODE      /* UNICODE 用プログラム */
#define STRICT      /* 厳密な型を利用 */
#define WIN32_LEAN_AND_MEAN /* コンパイルを高速化 */

#define COBJMACROS  /* C 言語用 COM マクロを利用 */

/* 基本ヘッダの取り込み */
#include "lnkfile.h"

/* 関数の実装 */
HRESULT ShortcutGetTarget(const wchar_t *fileName, wchar_t *target, unsigned int bufferSize) {

    return S_OK;
}

========== lnkfile.c ==========

Windows API + VC++ を使って開発する際は、
幾つかのマクロが重要な機能を果たす。

マクロ UNICODE を定義しておくと、
Unicode 対応版のプログラムを作成することになる。
Windows API は Unicode 対応と非対応の 2 つを持つが、
マクロ UNICODE によってどちらを使うか決定するのだ。

Unicode 対応の API は、そのほとんどが
Windows NT 以降でしか利用できないが、
現状の Windows OS の普及を考えるともういいだろう。

それに、COM は最初から Unicode なので、
Unicode 版を使うと文字コードを気にしなくて済む。

STRICT は、ハンドル型の型チェックを厳しくするためだ。

Windows には、HINSTANCE, HWND, HANDLE などの、
ハンドル型が数多く存在するが、
通常、これらはただの整数値として扱われ、
相互に代入することができてしまう。

STRICT を指定しておくことで、
間違ったハンドル型間で代入することを防ぐことができる。

WIN32_LEAN_AND_MEAN を定義しておくと、
通常のプログラムではまず使用しないであろう各種宣言を、
スキップし、コンパイル時間を短縮してくれる。
Windows 開発では、windows.h という巨大なヘッダを、
プログラムに取り込む必要があるので、効果は高い。

COBJMACROS は、今回の肝だ。
COM を C 言語で利用する際は、インタフェースの使用時に
少し複雑な構文を書く必要があるのだが、
COBJMACROS を宣言しておくと、
この記述を助けてくれる関数風のマクロを使えるようになる。

#include "lnkfile.h"
は、上で作成したヘッダファイルを取り込んだ。
別に lnkfile.h を使う必要はないのだが、
必要なヘッダの取り込みや、プロトタイプの指定があるため、
取り込んでおくと便利なのである。

さて、ここまで書いてやっと関数の実装になる。

……長くなりそうなので、今日は return S_OK; と、
成功を意味する値を返すだけにしておこう。



Copyright (c) 1994-2007 Project Loafer. All rights reserved.