COMとHRESULT

昨日の説明で一カ所間違いがありました。というか見逃していました。

アスペクト比を維持して表示するための動作として3つ(何もしない、ソフトウェア拡大、変形マッチング)がありましたが、もう一つ確認しました。それは

4. 画面中央に拡大せずに表示してしまう(リアルモード)

です。まさかこれを取っているゲームがあるとは・・・。

この動作しかないときはどうにかしてフルスクリーン「もどき」になるように設定を変えなければなりませんが、その設定には四苦八苦しました。

何のゲームかは教えることができませんが、ヒントは以下の通りです。

  • このblogを書いてる私のディスプレイのアスペクト比は16:9です。
  • 対象のゲームのアスペクト比はこのディスプレイのアスペクト比とは一致していません。かつ4:3でもありません。
  • このディスプレイでは[1280×720]の解像度での初期化ができないので(というか初期化できるものがなさそうな気が・・・)、無理矢理やろうとすると1600×900になります。

ま、それは放置しておいて、COMとHRESULTです。前にもちょっと話しましたが、COMオブジェクトはすべてIUnknownというインターフェイスを継承しています。

これが対象のオブジェクトの参照カウントを管理しているのでうまく使いましょう。

また、COMオブジェクトはWindows特有のシステムで、以下のような形で使用します。

  1. CoInitialize(というかCoInitializeEx)でライブラリを初期化
  2. CoCreateInstanceで対象のオブジェクトを作成して初期化する
  3. オブジェクトは必要なくなればReleaseを使って解放する
  4. CoUninitializeでライブラリを開放する

これは別のページでも書いてあることなので適当に探してみてください。で、COMではHRESULTという変数型を使用します。この変数型はCOMでのエラーコード(または成功コード)を返すことで

そのオブジェクトの動作が成功したかどうかを知らせます。WinAPI系がLRESULTなので、それと似たような感じです。以降、HRESULT型の変数はhrで記述します。Microsoftのサンプルコードもだいたいhrを使っています。

これには付随するマクロがあります。

SUCCEEDED(hr) => 指定した作業が成功したかどうか

FAILED(hr) => 指定した作業が失敗したかどうか

このマクロがあることからわかると思いますが、成功コードは一つではありません。成功してもいわゆる「問題があったけれどもその命令的には成功と見なせる」というコードがあります。

おもに成功コードと使われるのは以下の二つです。成功コードの先頭はすべてS_がついています。

コード 意味
S_OK 対象の処理は成功した。(汎用的な成功。DirectX系ではDD_OKやD3D_OKなどとも記述される)
S_FALSE 対象の処理を行う必要がなかった。[代表的な意味]

なので、完全な成功(あるいは失敗)を確認したいときは

if(hr == S_OK){ ... } //成功したときの処理
if(hr != S_OK){ ... } //失敗したときの処理

と書けますが、本来「成功した(処理として問題がなかった)」(あるいは失敗した)ことを確認するときは

if(SUCCEEDED(hr)){ ... } //成功したときの処理
if(FAILED(hr)){ ... } //失敗したときの処理

と記述すべきです。マクロの方がわかりやすいですが、私はほとんどの場合で何となく上の書き方を使っています。(説明書きで成功コードが複数存在し、そのすべてが成功と見なせる処理なら下で書きますが)

汎用のエラーコードとしては以下のようなものがあります。これはDirectShowのフィルタを実装するときにも登場するコードです。エラーコードの先頭はすべてE_がついています。

コード 意味
E_FAIL 汎用的な失敗
E_UNEXPECTED 予期しないエラーが発生した(例外が投げられたなど)
E_OUTOFMEMORY メモリ確保に失敗(メモリが足りないなど)
E_NOINTERFACE 対象のインターフェイスがサポートされていない(QueryInterfaceで対象のインターフェイスが無いときなど)
E_INVALIDARG 引数が正しく指定されていない
E_POINTER ポインタが正しくない(NULLポインタを渡されたときなど)
E_NOTIMPL 対象の機能が実装されていない

DirectX系の場合は先頭のE_をDDERR_やD3DERR_に変えてエラーコードをとっているものもありますが、コードの制約は同じものを使っています。

エラーコードの付け方としては参考になるので見てみるといいかもしれません。(MAKE_HRESULTというマクロを使います)


コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

この記事のトラックバック用URL