coLinuxは諦めた(笑)

今までの一連の流れの中でcoLinuxも試してみてたんです。このサイト様を参考にログインできるとこまで持っていったんですけど、なんと私のキーボードだと"|"が打てない!
pipe使えないじゃん!致命的!
ってことでお蔵入り…。結構よさそうな感じだったんですけどねー。

原因はキーボードにあるのは分かっています。
私の愛用しているキーボードはKinesis社製のErgo Elanってやつなんですよね。
InternationalKeyってのを今まで"\"と"|"用のキーとして使ってたわけですが、このキーってOSによって何が表示されるか変わるみたい。
今まで経験してきた環境では全部"\"と"|"だったのに、coLinux上では"."と">"になっちゃうです。

Kinesisはキーリマップできるんですけど、割り当て直せばいいんですけどちょっとメンドイ(笑)。
あと仕事の締切りが迫ってきたので試行錯誤の余裕がなくなってしまいました。

しょうがない。気は進まないけど、telnetで本番環境に接続しようか。
久々にvim使ったら色々コマンド忘れててまいったー。

Google Testのセットアップ(Cygwin編)

前回のように切ない事態になったわけですけども、新しいプロジェクトでもやっぱりTDDにチャレンジしてみようかと。
今度はLinuxC++です。ライブラリとリンクするようなこともありません。至ってシンプルな構成。まさに初めてのTDDにふさわしい!


Linux初めてだけどね…。


telnetgdbCUIデバッグとか苦痛すぎるので出来ればEclipseとか使いたいところ。ひとまずCygwin使ってWindows上でビルドできないか試してみました。まあ、肝心の本番プログラムは動かなかったのですけど、Google Testはビルドできたよってことでメモ残しておきます。

環境

手順

これまたGoogle TestのREADMEそのままですね。

  1. Cygwinのインストール
    • Devel/gcc-core
    • Devel/gcc-g++
    • Devel/make
  2. bash起動
  3. ${GTEST_DIR}/makeに移動
  4. make
    • ビルドが成功するとsample1_unittest.exeというユニットテストのサンプルができる
  5. ./sample1_unittest.exe
    • 実際に実行してみて動くかどうかのチェック

という感じでサンプル動きましたー。

最後に

本番プログラムからは下記ヘッダが見つからないってエラーが出るのです。

#include 
#include 

実はこの前にMinGWでも試してるんですよね…。こっちはpthreadが無いってエラーでしたが。
色々面倒くさいのでvmwareVirtualPC試してみようかな…。
でもvmware Playerは商用利用NGでVirtualPCはファイル共有が上手くいかなくて。

どの手段もあと一歩足りない…。

Google Testのセットアップ(Visual Studio編)

TDD(TestDrivenDevelopment)って一度やってみたいとずっと思ってたんです。
でもずっと組み込みC言語のクロスコンパイル環境というプアな環境だったためなかなかチャレンジが難しくできずにいました。
しかし今はVisual StudioWindows用アプリを書いています。これはチャンス!ということでまずはセットアップから。

環境

手順

基本的には参照先の通り。ただしライブラリへのリンクは#pragma commentではなくプロジェクトのプロパティにて行ないました。Debug/Release両方でユニットテストするかどうかは謎ですが、ソースコード上に書くと静的にリンクしてしまうのでプロパティに書くより自由度が減ると思ったためです。

  • プロジェクトのプロパティ | リンカ | 入力 | 追加の依存ファイル
    • Debug構成時:gtestd.lib gtest_maind.lib の追加
    • Release構成時:gtest.lib gtest_main.lib の追加

実環境への適用

サンプル動きましたー。じゃあ本番のプログラムでもやってみようか…とするところでまたつまづくわけです。どうやって既存のプロジェクトに当てはめていけばいいもんかと。
本当はこのページのようにユニットテスト用のTestプロジェクトを追加→Releaseビルド時はビルド対象から外す…としたかったのですけど、リンクエラーが解決できなくて断念(本番プログラムがサードパーティライブラリをスタティックリンクしまくってるせいだと思うんすけど)。
しょうが無いので、

  1. 構成マネジャでTestっていう構成を追加
  2. main関数だけ別ファイル化(main.cpp)
  3. Testフォルダをプロジェクトに追加し、この中にテストファイルを随時追加する
  4. Test構成時はmain.cppをビルド対象から外す
  5. Debug/Release構成時はTestフォルダ内の全ファイルをビルド対象から外す、main.cppをビルド対象とする

という感じで強引に。

これで本番のプログラムにおいてもユニットテストのオンオフが出来るようになりました。

それでもまだはまったこと

これ以降は完全に個人的な問題ですが。

  • 構造体メンバのアライメントに気をつけろ!
    • テスト被対象プロジェクトとGoogle Testプロジェクトの構造体メンバのアライメントは揃える必要があります。これをしないとビルドは通るのに実行時にエラーで落ちます(これに気づくのに時間がかかった…)。外部と通信するようなプログラムはアライメントを1にするかと思います。このようなときは要注意。
      • 構成プロパティ|C/C++|コード生成|構造体メンバのアライメント
  • #pragma packに気をつけろ!
    • プロパティ上は同じ設定でビルドしてあっても、ソースコード上で#pragma packしてるとやっぱりビルドは通るのに実行時にエラーで落ちます。

最後に

ここまで準備してさあやるぞって段になって急遽アサイン変更、このプロジェクトから離れることに。なんてこったい…。

画像をPPMフォーマットで保存する

ppmという拡張子の画像フォーマットがあります。
LinuxUnix系では一般的らしいのですが、ずっとWindowsだった私は今回はじめて知りました。
今回PPMフォーマットでのファイル保存にちょっと苦労してしまったので覚え書きを残しておこうと思います。

フォーマット

  • ヘッダ部とデータ部がある
  • ヘッダ部はASCII文字。ただし-改行はLFのみ。CRLFはNG。
    • 保存先ファイルはバイナリモード(wb)でファイルオープンする必要がある。
  • データ部はバイナリ(P6形式の場合、P3形式ならデータ部もASCIIらしいけど未検証)。
    • ピクセルオーダー、カラーオーダー共にBMPと異なる
      • ピクセルオーダー:左上→右下の順
      • カラーオーダー:R→G→Bの順

その他メモ

  • GIMPIrfanViewBMPPPMへ変換できます。
  • 保存先ファイルをテキストモード(w)でファイルオープンすると、1600x1200、2048x2048などで画崩れが発生することがありました(ドラクエ旅の扉みたいになる)。

Windows XP 32bitにおけるOpenAL-softのStatic Linkライブラリ化

OpenALというクロスプラットフォームのオーディオAPIがあります。

仕事上このライブラリを静的リンク(static link)で使うことになったのですが、どうやらOpenALにはWindows用の静的ライブラリ(static library)を出力するオプションがないみたいです(2010-7-27当時)。このためちょこっとオリジナルソースコードに手を入れて作成してみました。メンドウなことにVisualStudio用のソリューションファイルが同梱されておりません。CMakeというツールを一段かまさないといけません(初めて使った)。かな〜り自信無いですが誰かの参考になれば幸い。

なお、今回の仕事はサウンドバイスのエニュメレーションまで必要としなかったので、複数起動などまでは考慮していません。よって本家のWindowsブランチ(OpenAL-Windows)ではなくOpenAL-Softを対象としました。あしからず。

開発環境

DirectXは若干古いですが、ほかは大抵最新版を利用しました。

手順

  1. OpenAL Softをダウンロード&解凍(2010-7-27当時は1.12.854)
  2. コマンドプロンプトにてOpenALの./buildフォルダへ移動
  3. まずはOpenAL-SoftのREADMEに従ってVisual Studioソリューションファイルを作ります。ただしCMakeでは-DLIBTYPE=STATICを付けるところが通常とは異なります。
    1. cd C:\openal-soft-1.12.854\build
    2. "C:\Program Files\CMake 2.8\bin\cmake.exe" .. -DLIBTYPE=STATIC
  4. あとはVisual Studioでの作業。"./build/OpenAL.sln"を起動。
  5. OpenAL32のプロパティ設定を次のように変更
    1. ソリューションエクスプローラーのOpenAL32上で右クリック、Propertiesを選択。
    2. "Configuration Properties | C/C++ | Preprocessor | Preprocessor Definitions"に"OPENGL_STATIC"を追加
    3. "Configuration Properties | Librarian | General | Additional Dependencies"に"winmm.lib"を追加
    4. "Configuration Properties | C/C++ | Code Generation | Runtime Library"を親プロジェクトと同じ設定に変更
      • このときCMakeが勝手にプロジェクトファイルを更新しようとしますが、キャンセル&無視
  6. dllexport/dllimportさせないよう、オリジナルのソースコードからinclude/al.hとinclude/alc.hの該当部分を修正します。
    1. in .include/al.h
#if 0  // original >>>
 #if defined(AL_BUILD_LIBRARY)
  #define AL_API __declspec(dllexport)
 #else
  #define AL_API __declspec(dllimport)
 #endif
#else  // <<< original | custom >>>
 #ifdef OPENAL_STATIC
  #define AL_API
 #else
  #if defined(AL_BUILD_LIBRARY)
   #define AL_API __declspec(dllexport)
  #else
   #define AL_API __declspec(dllimport)
  #endif
 #endif  // <<< custom 
#endif  // if 0
    1. in include/alc.h
#if 0  // original >>>
 #if defined(AL_BUILD_LIBRARY)
  #define ALC_API __declspec(dllexport)
 #else
  #define ALC_API __declspec(dllimport)
 #endif
#else  // <<< original | custom >>>
 #ifdef OPENAL_STATIC
  #define ALC_API
 #else
  #if defined(AL_BUILD_LIBRARY)
   #define ALC_API __declspec(dllexport)
  #else
   #define ALC_API __declspec(dllimport)
  #endif
 #endif  // <<< custom 
#endif  // if 0
  1. DllMain()のDLL_PROCESS_ATTACH、DLL_PROCESS_DETACHの代替関数として次の関数をinclude/alc.hとOpenAL32/OpenAL32.cに追加します。
    1. in include/alc.h
#ifdef OPENAL_STATIC
/*
 * Allocation Management
 */
void InitialiseOpenAL( void );

void FinalizeOpenAL( void );
#endif  // OPENAL_STATIC
// <<<<< Added code by inazaki 2010.07.09


in OpenAL32/OpenAL32.c
// Added code by inazaki 2010.07.09 >>>>>
#ifdef OPENAL_STATIC
void InitialiseOpenAL( void )
{
    DllMain(NULL,DLL_PROCESS_ATTACH,NULL);
}

void FinalizeOpenAL( void )
{
    DllMain(NULL,DLL_PROCESS_DETACH,NULL);
} 
#endif  // OPENAL_STATIC
    1. in .OpenAL32/OpenAL32.c
#ifdef OPENAL_STATIC
void InitializeOpenAL( void )
{
    DllMain(NULL,DLL_PROCESS_ATTACH,NULL);
}

void FinalizeOpenAL( void )
{
    DllMain(NULL,DLL_PROCESS_DETACH,NULL);
} 
#endif  // OPENAL_STATIC
  1. あとはまあ一応全体ビルドも通るようにしておこうということでおまけでExamples/openal-info.cの冒頭にInitializeOpenAL()、末尾にFinalizeOpenAL()を追加
  2. 最後に全体のリビルドを実行

注意点

場合によっては下記リンクのように特定ライブラリを無視したりしなければならないかも。

よっしゃブログ始めてみんべ

仕事で全くの専門外を担当することになったりTwitterで色々見たりと刺激を受けたんで、自分でも何か発信できないかと思い立ちました。

日常のダラダラはTwitterでやってるんでブログは人様の役に立つことをメインでやっていこうかなと。
そうなるとやっぱ仕事でやってることだよねーってことでプログラミング関連が中心になると思います。

自己啓発として色々チャレンジしてみて結果報告みたいなのもしてみたいかな。

とはいうものの誕生日を機に始めるつもりだったのが早々にディレイしてるくらいなんで更新頻度はかなり低めになるでしょう。
それでは自分の書いた記事が誰かの助けになることを祈って。「あの中の蛙」の始まり始まり。