このアーカイブは同期化されません。 mixi の日記が更新されても、このアーカイブには反映されません。
続いて、関数を呼び出す側を作ろう。
プログラムとして実行できるように、
C 言語の起動関数を定義し、
実際にコンパイルして実行してみよう。
起動関数は、program.c で定義することにする。
Visual C++ + Windows 開発専用なので、
Unicode に特化して書いてみよう。
========== program.c ==========
#define UNICODE
#define STRICT
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
/* ShortcutGetTarget */
#include "lnkfile.h"
/* wprintf */
#include <stdio.h>
/* setlocale */
#include <locale.h>
/* 起動関数 */
int wmain(int argc, wchar_t *argv[]) {
const wchar_t *path =
L"C:\\Documents and Settings\\All Users"
L"\\Start Menu\\Windows Update.lnk";
/* リンク先を受け取るバッファ */
wchar_t target[MAX_PATH];
HRESULT result = S_OK;
/* Unicode => ANSI 変換で日本語を出力可能にする */
setlocale(LC_ALL, "Japanese");
/* ShortcutGetTarget を呼び出す */
result = ShortcutGetTarget(path, target, MAX_PATH);
/* 成功した場合 */
if (result == S_OK) {
/* テスト出力 */
wprintf(L"ファイル名 : %s\n", path);
wprintf(L"ショートカット先: %s\n", target);
}
return (int)result;
}
========== end of program.c ==========
Visual C++ のコンパイラにおいて、
コンソールアプリ(コマンドアプリ)を作る場合、
Unicode 対応の起動関数は、「wmain」という名前となる。
引数の argv も Unicode 対応で wchar_t となる。
今回は使わないので省略しても良いのだが、
書く癖をつけておいてもいいでしょ。
昨日同様、最初にマクロ定義とヘッダの取り込みをする。
別ファイルの ShortcutGetTarget 関数を使うので、
プロトタイプの定義された lnkfile.h を取り込んでおく。
そして、コンソール入出力に関係する、
stdio.h と locale.h も取り込んでおく。
さて、wmain 本体を書いていこう。
とりあえずは、ファイル名決めうちで書いてみる。
C 言語では、原則、変数の領域を確保しなければならない。
文字列を定義するためには、文字の配列領域が必要だ。
そのため、リンク先の文字列を受け取るために、
wchar_t target[MAX_PATH]; として、
MAX_PATH 文字分の文字配列領域を確保してある。
例外的に、文字列リテラルで文字列定数を定義する場合は、
それを格納する文字配列を定義しなくても、
それを示すポインタに格納することが可能である。
const wchar_t *path =
L"C:\\Documents and Settings\\All Users"
L"\\Start Menu\\Windows Update.lnk";
この文は、文字へのポインタ path を定義している。
通常、ポインタはメモリアドレスを示すため、
ポインタが指す領域を確保しておく必要があるが、
文字列リテラルで初期化する際は、
その文字列の領域は、自動的に確保されることになっている。
C 言語では、文字列リテラルは特別なのである。
このような例外を理解せずにポインタを使ってしまうと、
実際に有効なアドレスを示していないポインタに、
誤ってアクセスしてしまい、強制終了される事態になる。
Java などでは、参照型変数が null でない場合、
必ず有効なインスタンスが入っているが、
C 言語では、ポインタが指す先が、
常に有効であるとは限らないのである。
さて、次の setlocale は、
C 言語で定義されている関数であり、
プログラムで扱う言語を指定する。
Windows + Visual C++ で Unicode 入出力関数を使うと、
Unicode と標準の文字コード(ANSI) の変換が、
裏で自動的に行われる。
setlocale で Japanese を指定しておくと、
標準の文字コードが Shift_JIS になるので、
コンソール上に正常に日本語を表示することができる。
さて、ここでやっと ShortcutGetTarget を呼び出す。
引数にリンク先を受け取る文字バッファのアドレスと、
バッファの長さを引数で渡す。
確保しているメモリ領域を意識する C 言語では、
メモリの先頭+有効な長さという扱い方が多いのだ。
さて、関数が成功すると、S_OK が返るので、
コンソールにファイル名とリンク先を出力して終了。
では、これをコンパイルしてみよう。
Visual C++ IDE を使って開発している場合は、
メニューからビルドを選ぶだけで終わりだが、
ここでは、あえてコマンドを使ってみよう。
まず、コマンドプロンプトを起動し、
ソースファイルのあるディレクトリに移動しておく。
コンパイラのパスは事前に通しておくこと。
最近の Visual Studio では、
「Visual Studio 2005 コマンド プロンプト」のように、
処理系のパスを通した状態で実行できるメニューがある。
では、コンパイル⇒リンク⇒実行してみよう。
> cl /c lnkfile.c
> cl /c program.c
> link /out:test.exe lnkfile.obj program.obj ole32.lib
> test.exe
ファイル名 : C:\Documents and Settings\All Users\Start Menu\Windows Update.lnk
ショートカット先: %SystemRoot%\system32\wupdmgr.exe
cl でソースファイルをコンパイルし、
機械語のオブジェクトファイル (*.obj) を作成する。
link で、オブジェクトファイルを組み合わせて、
ロード可能なモジュール(実行ファイル)を作成する。
そして、すぐに test.exe を実行してみると、
ショートカットの情報が表示された。
ひとまずは成功である。