スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

wxString::Format などを boost::format で置き換える話

今年の初めに姫踊子草で使っている wxWidgets を 2.8 系から 2.9.4 に差し替えたのはいいが wxString::Format が厳しすぎて wxLogXXX の挙動に困るという話を書きました。

選択肢としては次のものがあったのですが。

  1. 地道に全ての wxString::Format, wxString::Printf, wxLogDebug はじめ wxLogXXXX 系統のすべてをチェックする、あるいは別の方法を使って書き直す
  2. 実行時にエラーが出てしまうのを諦めて見つかり次第モグラたたき的に修正する
  3. とりあえず応急措置として動作記録をとるのはやめておく
  4. なんとか元のコードを操作しなくてすむ代理手段を探す

最初のは理想ですが現実問題多すぎて無理、二つ目はさすがに利用者に迷惑かけすぎ、しょうがないので一時的に三つ目を採用し、ようやくこのたび四つ目に成功したっぽいのでそのご報告。成果実物については前ブログエントリの版2.0013号構築40番のとおり更新済み。

具体的な代理手段というのは、表題の通り boost::format を使う。

wxString::Format も boost::format も Unix-98 形式の %1$s みたいな表記をともに採用しているのと、実行時に止めないという点では一番信用できそうだったのが採用理由。

前者は printf 同様のカンマ区切り、後者は operator%() で繋いで引数を渡すという違いはマクロやテンプレートでなんとかしましょう、ということでできたのが下記のコード。

これで呼び出し側の wxLogDebug を Dbg, wxLogMessage を Msg と置き換えていって、ついでに wxString::Format も wxToBoostFormat に置き換えてしまえばまず実行時に止まったりはしなくなります。なるはずです。

注意点は wxWidgetsのヘッダよりも先に boost/format.hpp の include を済ませておくこと。でないとデバッグビルドができなくなります。

途中で動作を止めない、という意味で重要なのは f.exceptions(boost::io::no_error_bits) 、これ広域変数とかせめて構築子で指定できたらよかったんですけど、テンプレートコードの中でしか使わないから気にしないことにする。

可変数引数関数にCでは使えないC++の諸々を渡すのは危険。しかし可変数引数マクロならば問題はない、というのがミソ。後者は元々 C++ でなくて C の機能だとかなんとか。__VA_ARGS__ のあたり。

実行速度については別途実測調査してみたところ直接 wxLogXXXX を使うときに比べて2倍から2.5倍になるみたいです。if 文でログ自体不要の場合は弾いているので、姫踊子草の設定窓口で wxLogDebug を指定したりしない限りそこまでひどいことにはならないはずですが、そもそも背に腹は代えられません。

template wxString wxToBoostFormat(const std::wstring& fmt,const T0& p0,const T1& p1,const T2& p2,const T3& p3,const T4& p4,const T5& p5,const T6& p6,const T7& p7,const T8& p8) { boost::wformat f(fmt); f.exceptions(boost::io::no_error_bits); f%p0%p1%p2%p3%p4%p5%p6%p7%p8; return f.str(); }
template wxString wxToBoostFormat(const std::wstring& fmt,const T0& p0,const T1& p1,const T2& p2,const T3& p3,const T4& p4,const T5& p5,const T6& p6,const T7& p7) { boost::wformat f(fmt); f.exceptions(boost::io::no_error_bits); f%p0%p1%p2%p3%p4%p5%p6%p7; return f.str(); }
template wxString wxToBoostFormat(const std::wstring& fmt,const T0& p0,const T1& p1,const T2& p2,const T3& p3,const T4& p4,const T5& p5,const T6& p6) { boost::wformat f(fmt); f.exceptions(boost::io::no_error_bits); f%p0%p1%p2%p3%p4%p5%p6; return f.str(); }
template wxString wxToBoostFormat(const std::wstring& fmt,const T0& p0,const T1& p1,const T2& p2,const T3& p3,const T4& p4,const T5& p5) { boost::wformat f(fmt); f.exceptions(boost::io::no_error_bits); f%p0%p1%p2%p3%p4%p5; return f.str(); }
template wxString wxToBoostFormat(const std::wstring& fmt,const T0& p0,const T1& p1,const T2& p2,const T3& p3,const T4& p4) { boost::wformat f(fmt); f.exceptions(boost::io::no_error_bits); f%p0%p1%p2%p3%p4; return f.str(); }
template wxString wxToBoostFormat(const std::wstring& fmt,const T0& p0,const T1& p1,const T2& p2,const T3& p3) { boost::wformat f(fmt); f.exceptions(boost::io::no_error_bits); f%p0%p1%p2%p3; return f.str(); }
template wxString wxToBoostFormat(const std::wstring& fmt,const T0& p0,const T1& p1,const T2& p2) { boost::wformat f(fmt); f.exceptions(boost::io::no_error_bits); f%p0%p1%p2; return f.str(); }
template wxString wxToBoostFormat(const std::wstring& fmt,const T0& p0,const T1& p1) { boost::wformat f(fmt); f.exceptions(boost::io::no_error_bits); f%p0%p1; return f.str(); }
template wxString wxToBoostFormat(const std::wstring& fmt,const T0& p0) { boost::wformat f(fmt); f.exceptions(boost::io::no_error_bits); f%p0; return f.str(); }
template wxString wxToBoostFormat(const T& s) { return s; }

// 次のマクロ群は事態の重い順で並べている
// do while(0) は波括弧なし if 文に対応するため
// tOmOp という変な名前は呼び出し側を上書きしないようにするため
#define Ftl(...) do { if (wxLog::GetLogLevel() >= wxLOG_FatalError) { const wxString tOmOp = wxToBoostFormat(__VA_ARGS__); wxLogFatalError("%s", tOmOp); } } while(0)
#define Err(...) do { if (wxLog::GetLogLevel() >= wxLOG_Error) { const wxString tOmOp = wxToBoostFormat(__VA_ARGS__); wxLogError("%s", tOmOp); } } while(0)
#define Wrn(...) do { if (wxLog::GetLogLevel() >= wxLOG_Warning) { const wxString tOmOp = wxToBoostFormat(__VA_ARGS__); wxLogWarning("%s", tOmOp); } } while(0)
#define Msg(...) do { if (wxLog::GetLogLevel() >= wxLOG_Message) { const wxString tOmOp = wxToBoostFormat(__VA_ARGS__); wxLogMessage("%s", tOmOp); } } while(0)
#define Sts(...) do { if (wxLog::GetLogLevel() >= wxLOG_Status) { const wxString tOmOp = wxToBoostFormat(__VA_ARGS__); wxLogStatus("%s", tOmOp); } } while(0)
#define Vbs(...) do { if (wxLog::GetLogLevel() >= wxLOG_Info) { const wxString tOmOp = wxToBoostFormat(__VA_ARGS__); wxLogVerbose("%s", tOmOp); } } while(0)
#define Dbg(...) do { if (wxLog::GetLogLevel() >= wxLOG_Debug) { const wxString tOmOp = wxToBoostFormat(__VA_ARGS__); wxLogDebug("%s", tOmOp); } } while(0)

単引数の wxToBoostFormat がインチキくさいですが、テンプレートだけですませるにはこれが一番簡単ですし間違ってりゃコンパイルの時点でエラーも出るし、実害ないはずなので勘弁してください。

theme : プログラミング
genre : コンピュータ

姫踊子草版2.0013号構築40番公開

こんにちは、昨日付でキー入力入れ替えソフト姫踊子草の最新版を更新しております。

20130117

今回分

今年に入ってから開発上の都合で動作記録がほとんど取れなくなっておりましたが、復活させました。設定次第ではやりすぎ水準(=私だけが見てればいいレベル)で出力されます。お暇な方は wxLogDebug モードで動作させてみてください。おすすめはしませんが。

また、動作記録の保存先指定や、それらとは独立した OutputDebugString への出力可否指定もできるようになりました。

前回分

前回更新時にブログに書くのを怠っていたのでそちらの分も付記します。

設定窓口の下部に漢字二字で各項目ページを示したタブがありましたが、前回から三段表示+全体設定▽それ以外◆の記号を付与という形に変更しました。記号の意味は従来通りで、◆については同一コンピュータで配列その他各種設定を入れ替えられる趣旨のもの、▽はそうではない、同一コンピュータで同一設定になるものを配しています。

…XP と Windows 8 では綺麗に並ぶのに Vista ではあまり綺麗でないのはどうしてなんでしょうね?

theme : キーカスタマイズ
genre : コンピュータ

姫踊子草版2.0013号構築36番公開

姫踊子草の最新版を更新いたしました。

今回、補助鍵盤画像の設定周りで表示がおかしかったのを修正したのがおおきな一つ。前回同様 wxWidgets 2.9.4 の誤動作もしくは古い wxWidgets の誤動作回避コードが、修正された 2.9.4 でかえっておかしくなったとかそんなの。

別件で、実は1バイト書体の読み替え設定の際の挙動がおかしいんですけどそっちはまだ未修正。ほかの設定も併せていじることでなんとか更新保存を成立させてください。

もうひとつ大きなものが可搬版を32ビットWindowsで動かしたときのこと。通知領域メニューから版号を表示させてみてなんで64ビットExeとDllが動いていることになってるんかなと思ったら。

32ビットWindowsでは実行ファイルは一つだけ動いていればいいのに、なぜか二つも動作しておりまして。たまたま動作には実害がなかったようなのですが、メモリと実行速度を余分にとってしまうのでちゃんと今回直しました。

姫踊子草みたいなソフトは64ビットWindowsで動かす場合でも32ビット版を並列動作させなくてはなりません。そのために用意したものをなぜか32ビットWindowsでも動かしてた、そういうお話。

いつものとおり公式サイトより入手いただけます。

ところで旧版一覧の方が順序がぐちゃぐちゃになっているのっていつからだ…?


2013-01-27 追記: 旧版一覧の件はすでに修正しております。

theme : キーカスタマイズ
genre : コンピュータ

wxWidgets 2.9.4 で変更された(姫踊子草的に)重要な点

本記事は情報処理技術者向け。

wxWidgets 2.8 系から 2.9.4 に差し替えて姫踊子草の開発でひっかかった部分のメモです。

wxGridSizer系統の AddGrowableRow/Column 判定が厳しくなった

wxGridSizer, wxGridBagSizer, wxFlexGridSizer で AddGrowableRow や AddGrowableColumn を呼び出すとき、呼び出し時点でその行なり列なりが実在しないとダイアログ付きで警告されるようになりました。

wxURI::Unescape の問題で wxLaunchDefaultBrowser が動作しないことがある

file:/// プロトコルで ASCII 外の文字列を含む URI を渡すと wxURL::Unescape でエラー落ち。

で、 wxLaunchDefaultBrowser が内部で Unescape を呼び出すため、やっぱりエラー落ちします。もっとも file プロトコルではない通常のパスを渡せばいいだけなのでコードが呼び出す分には問題ないです。ユーザー指定の URL を受ける場合は問題になりますが。

__WXDEBUG__ マクロの使い方に変更がある

このため #ifdef __WXDEBUG__ で判定をとっているとリリースビルドでもデバッグコードが埋め込まれることがあります。

wxBitmapButton の変更

wxBitmapButton の機能は wxButton の基本性能になったため、互換上の定義でしかなくなりましたが、もう一点重要な変更が。

描画するビットマップは変更のたびに SetBitmap を呼び出さないと更新されません。メモリ節約のつもりで GetBitmap で受け取ったオブジェクトを変更するだけでは効果が反映されなくなりました。

wxString::Printf 関連の動作が厳しくなった

一番きついのはコレ。

wxString::Format とか wxLogXXXX 系統とかをたくさん使っているんですが、不適合と見なされるとリリースビルドでもダイアログを出して止まってしまうので新年明けてからの姫踊子草はほとんどログを出さなくなっています。

C++ の不定個数引数関数に一時オブジェクトを渡した場合の動作は「定義されていない」というのが年末に知った衝撃の事実でありまして。Visual C++ では適当によろしくしてくれますが他の環境では不定動作になるから wxWidgets 全体でも認めないことにしよう、ということになったらしい。

いやどーすんの姫踊子草のこれ。なんとかして wxString を使い続けるのか?それとも boost::format に片っ端から差し替えていくのか?

more...

theme : プログラミング
genre : コンピュータ

姫踊子草版2.0013号構築35番

皆様、しばらくぶりです。そして明けましておめでとうございます。

表題の通り、半年ぶりに姫踊子草の最新版を公開いたしました。

昨年秋に販売開始となった Windows 8 でスタート画面から Windows-D や B の操作が効かない件、英数配列を Ctrl などを押下しているときには適用しない設定になっている場合に限り問題解消しました。

入手は公式サイトより。年末年始なのでたぶん Vector さんへの登録はいつもよりやや遅れると思います。

なお、設定窓口の誤表示周りで新年に入ってから二回更新しております。新しい方の修正は誰も触ってなさそうなところばかりですが。詳細は履歴をどうぞ。


Windows 8 における姫踊子草なんですけども。 Windows ストアアプリでなければそこそこ動作するようです。ストアアプリだとかなか英数かの判別ができないようです。調査次第でなんとかなったりするのかもしれませんが。

Windows 8 を使い始めたついでに姫踊子草で使っている中間ソフトの差し替えを行いました。だいたいはよい方向に変わったのですが、逆に問題を起こしている部分をあります。

何か気になる動作がありましたらコメントなどでお知らせください。


ブログでは半年ぶりですが、ツイッターでは Windows 8 発売開始直後から縦書き記号誤表示問題の情報収集作業を行っていました。具体的にはWindows 8 でだけ縦書きの「…」「‥」「―」を誤って表示(マイクロソフトコミュニティ内)なんかをご覧ください。ワープロソフトや画像処理ソフトを巻き添えにする結構大きな問題だったりするので心当たりのある方はご確認を。姫踊子草全然関係ないですが。

theme : キーカスタマイズ
genre : コンピュータ

テンキーの0と.が使えなかった問題を修正(姫踊子草2.0013.33

ご無沙汰しております。いくら今年最初の記事だからってあけましておめでとうは止めておこうと思った鈴見咲です。

先日当ブログのコメントにてテンキーの 0 及び . を受付・出力しないというご連絡がありました。調べてみたところご指摘の通り姫踊子草に問題があったのでおよそ半年ぶりに最新版姫踊子草を公開いたします。

公式サイトにて、通常版・可搬版ともに版2.0013号構築33番を入手いただけます。例によってベクターでの公開については、すでに申請しましたので公開までしばらくお待ち下さい。


半年経つとビルドから公開までの手順を忘れかけていたりとか何とか。

theme : キーカスタマイズ
genre : コンピュータ

XP でロック解除したときの不具合修正(姫踊子草2.0013.32

こんばんは、姫踊子草最新版更新のお知らせです。今回の主な対象は Windows XP です。

Windows XP で Windowsキーを押しながら L キーを押すとコンピューターのロックがかかります。で、そのロックを解除した後、姫踊子草が事実上動作していないというご報告がありました。

当ブログにおける初回コメントの時点で Windows キーが押されっぱなしの扱いになっていることを教えていただきまして、実際その通り、姫踊子草の内部情報がおかしなことになっていましたのでそれを修正したものです。

実際の処理は「ロックから復帰したらすべてのキーを離したものとする」というものになってるんですが、さしあたりそれで問題なかろうかと存じます。

いつものとおり、最新版は公式サイトより入手いただけます。版2.0013号構築32番です。


今回初めて可搬版の更新になるわけですが、可搬版の更新は公開しているインストーラーを使って以前に可搬版を接地したフォルダに上書きするようにしてください。そうでないと、各種設定とパスワード入力がやり直しになってしまいます。

なお、ブログのコメントにて不具合報告などいただける場合は、特にどの記事のコメント欄をお使いいただいてもかまいません。後続のやりとりについては関連記事の更新があるまで同じ記事のコメント欄にしていただきたいですが、最初に古い記事に書いたせいで迷子になったとかいうときは最新記事に継続なさってもかまいません。外にコメントされる方がいなければ左側「最近のコメント」欄で当該記事にとべますし。

theme : キーカスタマイズ
genre : コンピュータ

リンク
RSSフィード
ブログ内検索
最近のトラックバック
月別アーカイブ
ブロとも申請フォーム

この人とブロともになる

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。