Archive for the ‘C++’ Category

Visual C++ 2010 を少し使ってみたんだけど、これは酷い。
前回の投稿で「最新版出たよ、なかなか良さそう!」と書いたのに、蓋を開けたら何とやらですよ。
良くなった点も当然あるんだけど、それ以上に駄目な点が多すぎる。

・テキストエディタがへぼすぎる。メモ帳に劣る -> Visual Studio 2010のword wrapの遅さ
・でかいヘッダインクルードするとファイルサーチでしばらく止まる
・C++0x 対応のお粗末さ
・vcproj 形式からのコンバートミスが多い
MPLPPL あんまり早くない (OpenMP で良いです)
・プロパティ弄っていると突然ちらついて、プロパティウィンドウが背景に溶け込む (XPだから?環境次第?)
・プロパティの構成切り替えだけでもたつく
・プロパティの保存も遅い、ちょっと固まる

他にも stdint.h が間違っているとか、ヘルプ使いづらいとか、その他たくさんの不満が聞こえてきます。(twitterで)
これにお金出すのは勿体無い、ね。

今回は Express Edition で。
Hotfix はやくきて。

Microsoft Visual Studio 2010
http://www.microsoft.com/japan/visualstudio/

リリースされました。
日本語版の発売は 4/20 だそうです。
英語版ですが、さっそく Visual C++ 2010 を試してみました。

RC 版では既に軽快だったかもしれませんが、beta2 では重すぎて使い物になりませんでした。
そんな IDE も、リリース版ではかなり軽快です。

コードを書いていると、構文チェックしてくれたり、インテリセンスの仕組みが変わって賢くなっているのがわかります。

C++0x の機能は完全にはサポートされていませんが、いくつか取り込まれました。
[Visual C++ Team Blog : C++0x Core Language Features In VC10: The Table]
http://blogs.msdn.com/vcblog/archive/2010/04/06/c-0x-core-language-features-in-vc10-the-table.aspx

STL も 中身を見てみたところ、Rvalue references 対応しているみたいです。
最適化レベルも上がっているので、VC++ 2010 でコンパイルするだけで実行速度が上がりそうすね。

価格は従来より割高?
Standard Edition がなくなり、有料版の一番下のモデルが Professional Edition になったみたいです。エディションが最近のWindows OSっぽくなった。
価格一覧 http://www.microsoft.com/japan/msdn/vstudio/2010/product/price/default.aspx

発売後、一定期間のみ安く販売する 「Microsoft Visual Studio 2010 Professional – Standard Edition 乗り換え優待パッケージ」があるみたいです。
これはアップグレード版になりますが、従来どおり Express Edition からでもアップグレードできるのでお得ですね。

自動整形機能のイライラを軽減するGoogle Syntax Highlighterプラグイン

どんな感じになるだろう。
ログ周りを追加してたコードの破片をぺたり。

#ifdef USE_DIRECTX8
    typedef D3DCAPS8 D3DCAPSX;
#endif

#ifdef USE_DIRECTX9
    typedef D3DCAPS9 D3DCAPSX;
#endif

#ifdef USE_DIRECTX10 // 今のところ未使用
    typedef D3DCAPS10 D3DCAPSX;
#endif

    D3DCAPSX caps;
    ZeroMemory(&caps, sizeof(D3DCAPSX));
    pDevice_->GetDeviceCaps(&caps);

    struct local {
        static const TCHAR* check(const bool v) {
            return v ? _T("○") : _T("×");
        }
    };

    typedef boost::format format;
    typedef TreeLogger logger;

    logger root("D3DCAPS", ofs, true);

おぉ、結構いい感じ!!

C++本16冊すべて届きました
C++本を積んでみた

C++本を積んでいるのを見て、自分も整理も兼ねて積んでみた。
明らかに足りていない本があるんだけど、会社か・・・
book

稲葉さんの Boost 本古いよ。でも第3版を待ったほうが良さそう。
よく見ると C++/CLI 混じってた。

squirrel のバージョンが新しくなってました。
Squirrel 本家

2.2.3 の変更点まとめ
今回から SQUSEDOUBLE を利用してコンパイルすることで、内部で使用している浮動小数点を float -> double にすることが出来るらしい。
合わせて、_floatsize_ で設定されている浮動小数点のバイト数が取得可能。
デバッグ用の関数として sq_getfunctioninfo が追加されてる。
sq_getstackinfos 関数と合わせて利用するといいかも。
sqstd_format は printf と同様のフォーマットが利用できる。
フォーマット文字列はスタック上に配置して、sqstd_format にはスタックのインデックスを渡す形になる。

以下、変更点の引用

***version 2.2.3 stable***
-added sq_getfunctioninfo
-added compile time flag SQUSEDOUBLE to use double precision floats
-added global slot _floatsize_ int the base lib to recognize single precision and double precision builds
-sq_wakeupvm can now resume the vm with an exception
-added sqstd_format
-generators can now be instantiated by calling sq_call() or closure.call()
-fixed a bug in sqstd_printcallstack(thx takayuki_h)
-fixed modulo by zero(thx jup)
-fixed negative enums and constants
-fixed generator crash bug if invoked as tail call (thx Mr.Accident)
-fixed some minor bug

***version 3.0 alpha 2***
-added real free variables(thx Paul Ruizendaal)
-added refactored function call implementation and compiler(thx Paul Ruizendaal)
-added sq_getfunctioninfo
-added compile time flag SQUSEDOUBLE to use double precision floats
-added global slot _floatsize_ int the base lib to recognize single precision and double precision builds
-sq_wakeupvm can now resume the vm with an exception
-added sqstd_format
-now blobs can be cloned
-generators can now be instantiated by calling sq_call() or closure.call()
-added compile time flag SQUSEDOUBLE to use double precision floats
-fixed debughook bug
-fixed cooroutine error propagation

下記のコードは、普通に通るよね。

C++:
  1. #include <boost/shared_ptr.hpp>
  2. #include <iostream>
  3.  
  4. int main(int argc, char** argv)
  5. {
  6.     boost::shared_ptr<int> p;
  7.     if (p == NULL) {
  8.         std::cout <<"null" <<std::endl;
  9.     }
  10.  
  11.     return 0;
  12. }

んで、NULL を置き換えてたらコンパイラが落ちました。

C++:
  1. //! ぬるぽ
  2. //! http://ja.wikibooks.org/wiki/More_C%2B%2B_Idioms/nullptr
  3. // const オブジェクトであって、
  4. const class nullptr_t
  5. {
  6. public:
  7.     // 任意の非メンバ型のヌルポインタや、
  8.     template<class T> operator T*() const { return 0; }
  9.  
  10.     // 任意のメンバ型のヌルポインタに変換可能であって、
  11.     template<class C, class T> operator T C::*() const { return 0; }
  12.  
  13. private:
  14.     void operator&() const// アドレスを取得することができない。
  15. } nullptr = {};
  16.  
  17.  
  18. //! NULL 値
  19. #undef  NULL
  20. #define NULL nullptr
  21.  
  22. #include <boost/shared_ptr.hpp>
  23. #include <iostream>
  24.  
  25. int main(int argc, char** argv)
  26. {
  27.     boost::shared_ptr<int> p;
  28.     if (p == NULL) {
  29.         std::cout <<"null" <<std::endl;
  30.     }
  31.  
  32.     return 0;
  33. }

fatal error C1001: コンパイラで内部エラーが発生しました。
(コンパイラ ファイル 'msc1.cpp'、行 1393)
この問題を回避するには、上記の場所付近のプログラムを単純化するか変更してください。
詳細については、Visual C++ ヘルプ メニューのサポート情報コマンドを
選択してください。またはサポート情報 ヘルプ ファイルを参照してください。

何も落ちなくてもなぁ。。
ちなみに if (p != NULL) でも落ちました。

しばらく実家に帰っていました。
TrickDiary で公開されている バグベアード -bugbeard- 面白そうですね。
TrickDiary
バグベアード -bugbeard-
プロファイラとか普通に使える子だと思います。

またハマったのでメモしておきます。

VisualStudio にプリコンパイル済みヘッダってあるじゃないですか。
今日久しぶりに使ってハマリマシタ。

ちゅーのは、 #include の部分。
普通に使う分には、#include "PCH.h" と各cppファイル等に書けばいける。
でも自分は #include "./PCH.h" と書いてハマリマシタ。
はまったってよりエラーなんだけど。

./ をつけるだけで駄目なのか・・・(汗

# PCH.h とかって最終的に「必ずインクルード」に設定しちゃうんだけどね。。

明日はCEDEC 2008 ですね。Squirrel のセッションは聞いてきますよー。

さて、今日はコメントにもありました sq_readclosure/sq_writeclosure/sq_compilebuffer を使ってみます。
これらは SqPlus のものではなく、Squirrel の関数ですね。

まずは簡単に使うだけの話。

sq_compilebuffer は SqPlus 版があるので、SqPlus::CompileBuffer を使います。
これはメモリ上のスクリプトをコンパイルし、スタックに積むというもの。

C++:
  1. // スクリプト
  2. const SQChar script[64] = _T("print(\"hogehoge-\");");
  3.  
  4. // compilebuffer 部分。
  5. SqPlus::CompileBuffer(script);

次に sq_readclosure。
これはコンパイル済みのスクリプトを読み込むというもの。
sq_readclosure も SqPlus で一発。

C++:
  1. // コンパイル済みスクリプトの読み込み
  2. SquirrelObject obj = SquirrelVM::CompileScript(_T("helloworld.cnut"));

実はSqPlus を使わなくても sqstd_loadfile 関数がヘッダをチェックして自動的に読み込んでくれるのです。おいしいです。

最後に sq_writeclosure。
VMに積まれているスクリプトをバイナリで吐き出すというもの。
SqPlus には無いので、Squirrel のものを使います。

C++:
  1. // バイナリで書き出す
  2. sqstd_writeclosuretofile(vm, _T("helloworld.cnut"));

てことで、簡単に使えます。
でもめんどくさい方法もあります。それはまた次回!

前回は C++ 側の関数やクラスを Squirrel 側で呼び出したので、今回はその逆です。

C++:
  1. // main.cpp
  2. #include <iostream>
  3. #include <sqplus.h>
  4.  
  5. #ifdef _DEBUG
  6. #  pragma comment(lib, "squirrelD.lib")
  7. #  pragma comment(lib, "sqplusD.lib")
  8. #  pragma comment(lib, "sqstdlibD.lib")
  9. #  pragma comment(lib, "sqdbglibD.lib")
  10. #else
  11. #  pragma comment(lib, "squirrel.lib")
  12. #  pragma comment(lib, "sqplus.lib")
  13. #  pragma comment(lib, "sqstdlib.lib")
  14. #  pragma comment(lib, "sqdbglib.lib")
  15. #endif //_DEBUG
  16.  
  17. int main(int argc, char** argv)
  18. {
  19.     SquirrelVM::Init();
  20.  
  21.     //----------------------------------------------------
  22.     // スクリプトの読み込みとコンパイル
  23.     //----------------------------------------------------
  24.     SquirrelObject obj = SquirrelVM::CompileScript(_T("helloworld.nut"));
  25.  
  26.  
  27.     //----------------------------------------------------
  28.     // スクリプトの実行
  29.     //----------------------------------------------------
  30.     try {
  31.         SquirrelVM::RunScript(obj);
  32.  
  33.         //----------------------------------------------------
  34.         // Squirrel 側の関数を呼び出す
  35.         // ※ まず SquirrelVM::RunScript の呼出しが必要!!
  36.         //----------------------------------------------------
  37.         // template のパラメータは戻り値の型, 関数名を指定
  38.         SqPlus::SquirrelFunction<void>(_T("func01"))();
  39.         // 引数付き関数を呼び出す
  40.         SqPlus::SquirrelFunction</void><void>(_T("func02"))("fuga");
  41.         // 戻り値の型を指定
  42.         std::cout <<SqPlus::SquirrelFunction<float>(_T("func03"))() <<std::endl;
  43.     } catch (SquirrelError& e) {
  44.         // error 処理
  45.         std::cout <<e.desc <<std::endl;
  46.     }
  47.  
  48.     SquirrelVM::Shutdown();
  49.  
  50.     return 0;
  51. }

C++:
  1. // helloworld.nut
  2. function func01() {
  3.     print("call : func01()");
  4. }
  5.  
  6. function func02(var) {
  7.     print("call : func02(), " + var);
  8. }
  9.  
  10. function func03() {
  11.     print("call : func03()");
  12.     return 3.14;
  13. }

cl /EHsc /MT /DNOUNICODE /I..\SQUIRREL2_1_1_sqplus_25\sqplus /I..\SQUIRREL2_1_1_sqplus_25\squirrel /I..\SQUIRREL2_1_1_sqplus_25\include main.cpp /link /LIBPATH:..\SQUIRREL2_1_1_sqplus_25\lib

実行結果

call : func01()
call : func02(), fuga
call : func03()
3.14

コードを見てもらうとわかるように、非常に簡単に Squirrel 側の関数を呼び出せます。
Squirrel では class の定義もできますが、それを C++ 側で使うのはちょっとわかりません。
# わかる人教えてください。

今回の注意点は、Squirrel の関数呼び出しは SquirrelVM::RunScript の後に行うこと!
まぁ、当然っちゃ当然ですね。

ではまた次回!