Archive for the ‘Program’ Category

windows vista sp2 が来てました。
家に帰ったらさっそく入れてみます。

colinux 0.7.4 が来てました。
カーネルの更新や、ネットワークブリッジの更新なんかがあるみたい。
でも vista 64bit には相変わらず非対応。。

visual studio 2010 beta1 が一般公開されてます。
STL の見直しや、一部 C++0x 対応などがあるらしいです。

windows 7 RC が一般公開されています。

windows xp 入手困難に
新しい windows が見えてきましたけど、xp の在庫がなくなって来たようです。
欲しい人はお早めに。

 
amazon のアフィリエイトアカウント取ってみた。
ぶっちゃけアフィリエイトはどうでもいいんだけど、写真付きでリンク貼れるのが便利なのよね。

最近読んだ本

きじねこの高木氏の本。
組み込みといわず、C/C++のちょっとマイナーな話が面白い。


Faith and Brave のアキラ氏、東方算程譚のεπιστημη氏の共著。
template の仕組みやテクニックについてわかりやすく書かれている。
Modern C++ Design には挫折してしまったという人はこちらオススメ。

今読んでる本


まだ全然読めてないー

ここ3日くらい javascript の仕事をやっている。
javascript は初めてだけど、意外と簡単だなーと仕事してたら setTimeout でちょっとはまった。

setTimeout 関数は、指定した関数を任意の時間後に再度実行指定する関数。

setTimeout(”hoge()”, 1000); // 1000ミリ秒後に hoge() を呼び出す

自分がちょっとはまったのは引数付きの関数呼び出しについて。
setTimeout(”hoge(” + value + “)”, 1000); のように書いてたんだけど、これは間違い。

正しくは下記のように書く。
setTimeout(”hoge(’” + value + “‘)”, 1000);

シングルクォートがミソなのね!!

プログラムネタで何か書きたいけどネタが無いー。
ということで思い出したようなネタを。

よくあるコード。エラーチェックは長くなるので省く。

C++:
  1. FILE* fp = fopen("file.bin", "rb");
  2.  
  3. // サイズ知りたい!
  4. fseek(fp, 0, SEEK_END);
  5. size_t size = ftell(fp);
  6. fseek(fp, 0, SEEK_SET);
  7.  
  8. fclose(fp);

※ バイナリモードで SEEK_END を指定した場合、期待通りに動作するかは不定です。

Visual Studio + Windows ではちゃんと動いてるけど、こういうのは心に留めておくべきよね。

普段使うのは MultiByteToWideChar とかな自分です。
変換関数は CのランタイムとWin32 API が用意されているけど、確か挙動が違うとどっかに書いてあったんだよね。
ぐぐったら出てきました -> 理ろぐ

自分で調べてなかったので、調べたくなりました。コードは 理ろぐ のを改造。
結論から言うと、locale 設定するだけでどちらでも正しい結果が出ます。

まぁ、ここまでが序章。
locale 設定しなくても Win32 API の方は正しく動いているように見えますので確認します。

C++:
  1. #include <iostream>
  2. #include <locale>
  3. #include <iomanip>
  4. #include <stdlib .h>
  5. #include <windows .h>
  6.  
  7. using namespace std;
  8. const int ARRAY_SIZE = 64;
  9.  
  10. std::ostream& couthex(const int n) {
  11.     return cout <<"Ox" <<setw(n) <<setfill('0') <<setbase(16);
  12. }
  13.  
  14.  
  15. void dump(unsigned char *data) {
  16.     for (int i=0; ; i++) {
  17.         if (i%16 == 0 && i != 0) cout <<endl;
  18.         couthex(2) <<static_cast<int>(*(data+i)) <<" " <<flush;
  19.  
  20.         if ((*(data+i) == 0) && (*(data+i+1) == 0)) break;
  21.     }
  22.  
  23.     cout <<endl <<endl;
  24. }
  25.  
  26.  
  27. bool charToWchar(const char* src, wchar_t* dst1, wchar_t* dst2) {
  28.     ::ZeroMemory(dst1, sizeof(wchar_t) * ARRAY_SIZE);
  29.     ::ZeroMemory(dst2, sizeof(wchar_t) * ARRAY_SIZE);
  30.  
  31.     bool retval = true;
  32.     if (::mbstowcs(dst1, src, sizeof(wchar_t) * ARRAY_SIZE) == -1) {
  33.         cout <<"mbstowcs : error" <<endl;
  34.         retval = false;
  35.     }
  36.  
  37.     if (::MultiByteToWideChar(CP_ACP, 0, src, -1, dst2, sizeof(wchar_t)* ARRAY_SIZE) == 0) {
  38.         cout <<"MultiByteToWideChar : error" <<endl;
  39.         retval = false;
  40.     }
  41.  
  42.     return true;
  43. }
  44.  
  45.  
  46. bool wcharToChar(const wchar_t* src, char* dst1, char* dst2) {
  47.     ::ZeroMemory(dst1, sizeof(char) * ARRAY_SIZE);
  48.     ::ZeroMemory(dst2, sizeof(char) * ARRAY_SIZE);
  49.  
  50.     bool retval = true;
  51.  
  52.     if (::wcstombs(dst1, src, sizeof(char) * ARRAY_SIZE) == -1) {
  53.         cout <<"wcstombs : error" <<endl;
  54.         retval = false;
  55.     }
  56.  
  57.  
  58.     if (::WideCharToMultiByte(CP_ACP, 0, src, -1, dst2, sizeof(char)* ARRAY_SIZE, 0, 0) == 0) {
  59.         cout <<"WideCharToMultiByte : error" <<endl;
  60.         retval = false;
  61.     }
  62.  
  63.     return true;
  64. }
  65.  
  66.  
  67. int main(int argc, char** argv)
  68. {
  69.     const char    csrc[]"Mrブギータンブリンマン";
  70.     const wchar_t wsrc[] = L"Mrブギータンブリンマン";
  71.     char    cdst1[ARRAY_SIZE] = "";
  72.     char    cdst2[ARRAY_SIZE] = "";
  73.     wchar_t wdst1[ARRAY_SIZE] = L"";
  74.     wchar_t wdst2[ARRAY_SIZE] = L"";
  75.  
  76.     // 1ループ目はロケール設定なし
  77.     // 2ループ目はロケール設定あり
  78.     for (int i=0; i&lt;2; i++) {
  79.         // マルチバイト文字 -> ワイド文字
  80.         {
  81.             charToWchar(csrc, wdst1, wdst2);
  82.             cout <<"mbstowcs : " <<endl;
  83.             dump(reinterpret_cast<unsigned char*>(wdst1));
  84.             cout <<"MultiByteToWideChar : " <<endl;
  85.             dump(reinterpret_cast<unsigned char*>(wdst2));
  86.         }
  87.         // ワイド文字 -> マルチバイト文字
  88.         {
  89.             wcharToChar(wsrc, cdst1, cdst2);
  90.             cout <<"wcstombs : " <<endl;
  91.             dump(reinterpret_cast<unsigned char*>(cdst1));
  92.             cout <<"WideCharToMultiByte : " <<endl;
  93.             dump(reinterpret_cast<unsigned char*>(cdst2));
  94.         }
  95.  
  96.         // locale 設定
  97.         cout <<"-- set locale --" <<endl;
  98.         locale::global(std::locale("japanese"));
  99.     }
  100.  
  101.     return 0;
  102. }

実行結果

mbstowcs :
Ox4d Ox00 Ox72 Ox00 Ox83 Ox00 Ox75 Ox00 Ox83 Ox00 Ox4d Ox00 Ox81 Ox00 Ox5b Ox00
Ox83 Ox00 Ox5e Ox00 Ox83 Ox00 Ox93 Ox00 Ox83 Ox00 Ox75 Ox00 Ox83 Ox00 Ox8a Ox00
Ox83 Ox00 Ox93 Ox00 Ox83 Ox00 Ox7d Ox00 Ox83 Ox00 Ox93 Ox00

MultiByteToWideChar :
Ox4d Ox00 Ox72 Ox00 Oxd6 Ox30 Oxae Ox30 Oxfc Ox30 Oxbf Ox30 Oxf3 Ox30 Oxd6 Ox30
Oxea Ox30 Oxf3 Ox30 Oxde Ox30 Oxf3 Ox30 Ox00

wcstombs : error
wcstombs :
Ox4d Ox72 Ox00

WideCharToMultiByte :
Ox4d Ox72 Ox83 Ox75 Ox83 Ox4d Ox81 Ox5b Ox83 Ox5e Ox83 Ox93 Ox83 Ox75 Ox83 Ox8a
Ox83 Ox93 Ox83 Ox7d Ox83 Ox93 Ox00

-- set locale --
mbstowcs :
Ox4d Ox00 Ox72 Ox00 Oxd6 Ox30 Oxae Ox30 Oxfc Ox30 Oxbf Ox30 Oxf3 Ox30 Oxd6 Ox30
Oxea Ox30 Oxf3 Ox30 Oxde Ox30 Oxf3 Ox30 Ox00

MultiByteToWideChar :
Ox4d Ox00 Ox72 Ox00 Oxd6 Ox30 Oxae Ox30 Oxfc Ox30 Oxbf Ox30 Oxf3 Ox30 Oxd6 Ox30
Oxea Ox30 Oxf3 Ox30 Oxde Ox30 Oxf3 Ox30 Ox00

wcstombs :
Ox4d Ox72 Ox83 Ox75 Ox83 Ox4d Ox81 Ox5b Ox83 Ox5e Ox83 Ox93 Ox83 Ox75 Ox83 Ox8a
Ox83 Ox93 Ox83 Ox7d Ox83 Ox93 Ox00

WideCharToMultiByte :
Ox4d Ox72 Ox83 Ox75 Ox83 Ox4d Ox81 Ox5b Ox83 Ox5e Ox83 Ox93 Ox83 Ox75 Ox83 Ox8a
Ox83 Ox93 Ox83 Ox7d Ox83 Ox93 Ox00

VS2008 st でコンパイルしました。
cl /EHsc /DWIN32 /MD /D_NODEBUG /D_CONSOLE convert.cpp

ちとソースが長いですが、結果を見ると locale 設定前でも Win32 API の方の変換は正しいことが確認できます。
ランタイムの方は locale を設定しないと、変換エラー出てますね。 (wcstombs)

windows で文字列の変換を行うときは Win32 API がよさそうですね。 Continue reading ‘VisualStudio でのマルチバイト文字とワイド文字の変換’ »

久しぶりに Qt [Qt 4.4.0 OpenSource Edition] を弄っていたときのこと。
何だか moc が動かない。

やってることとしては windows 上で CL.exe(9.00.21022.08) でビルドをする。
qmake makefile を作り、nmake でビルドする感じです。
ただこれだけのことなんだけど、moc_hogehoge.cpp といったファイルが生成されていない。
コンソールで moc src.h -o dst.cpp と叩いても動かない。これはおかしい。

解決はしたんだけど、utf16 のファイルを moc にかけることができない模様。utf-8 とかも試してみると駄目なのかもしれない。(未確認)
ファイルを Shift_JIS にしたら直った。

何とも微妙なはまりっぷりだったなぁorz (1時間くらい悩んだよ)

会社でコードを眺めているとこういうのがあったりする。

C++:
  1. class Hoge
  2. {
  3. public:
  4.     Hoge() :
  5.     one_(new int),
  6.     two_(new int),
  7.     three_(new int),
  8.     riderKick_(new int)
  9.     {}
  10.  
  11.     ~Hoge() {
  12.         delete one_;
  13.         delete two_;
  14.         delete three_;
  15.         delete riderKick_;
  16.     }
  17.  
  18. private:
  19.     int* one_;
  20.     int* two_;
  21.     int* three_;
  22.     int* riderKick_;
  23. };

デンジャラス。
何がデンジャラスかがわからない人はデンジャラスだぜ。

Seasons 氏のブログで書かれていますが、Visual C++ 2003, 2005, 2008 で言語仕様がそれぞれ微妙に変化(進化?)してますよね。
# C99対応はまだですが。可変長配列使いたいな

2003 では、

C++:
  1. class Hoge{
  2.     static void f();
  3.     static int v;
  4.     static const int VALUE = 100;
  5.  
  6.     int array_[VALUE];
  7. };
  8.  
  9. int main(int argc, char** argv)
  10. {
  11.     return 0;
  12. }

が許されていませんでした。(定義ないでしょ?ってコンパイラに言われた気がします)
なので、プログラマは enum ハックを使って配列の添え字としたりしていたのです。
ちなみに上記のソースは 2005 と 2008 では普通にコンパイルが通ります。

要するに、言いたいのは

static const int VALUE = 100; のように書くことで定数定義もできる。(2003以前では enum { VALUE = 100 }; のようにしてました)
これは知ってた。

class 宣言で static な変数やら関数を書いたら、定義しなければならないと思っていたが、利用しない場合、定義は必要ない。
こっちは知らなかった。

# あー、2003で確認したいなぁ。会社のPCで試してみるかな。

Bitmap を作成できないんですな。
可能なのはファイルとリソースだけぽい。

メモリ上のデータから読めると便利なのになぁー。

表題の通りです。
Qt では基本的にメッセージ処理を気にせず実装できるようになっとります。(隠されてます)
ですが、メッセージ処理を行いたい場面は多々あります。(通信関係とかDirectShow を使ったりとか)

ってことで、軽くまとめておきます。
自分の環境は下記
OS : Windows Vista Ultimate SP1 32bit
Qt : 4.4RC (Open Source)
VS : 2008 Standard

ってことでさくっとやっちゃいます。
Qt で メッセージを取得するのは QWidget::winEvent です。
こいつを再実装することで実現します。

C++:
  1. bool Window::winEvent(MSG* message, long* result)
  2. {
  3.     using namespace std;
  4.  
  5.     switch (message->message) {
  6.     case WM_KEYDOWN:
  7.         cout <<"push!!" <<endl;
  8.         *result = 0;
  9.         return true;
  10.     };
  11.  
  12.     return false;
  13. }

とりあえず、キーボードのキーが押されたら push!! と表示します。
戻り値に関しては、true を返すと Qt のメッセージ処理を行いません。
false を返すと、Qt のメッセージ処理も行われます。

MSG構造体(WinUser.hにて定義)に wparam, lparam も入っているので普通にメッセージ処理ができると思います。

ぐぐったら最初に出てきた y_mashiro 氏のページ見ながらビルドした。
何か一回エラー出てとまったけど、もう一回ビルドし直したらうまくいったみたい(何だそりゃ
clean はしてない。何でエラー出たんだろう。コンパイルは時間かかるから原因調べるのしんどいっす。

使ったオプションは
-platform win32-msvc2005
これだけ。

QTDIR とか環境変数指定って必要ないんだっけかな。
ともあれ、vista + VS2008 でもビルドはできましたとさー。