2006 年 10 月 12 日 23 時 54 分

実際にファイルから読み出す


このアーカイブは同期化されません。 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 を実行してみると、
ショートカットの情報が表示された。
ひとまずは成功である。



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