Archive for the ‘Visual Studio’ 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 からでもアップグレードできるのでお得ですね。

http://www.itmedia.co.jp/enterprise/articles/0910/20/news056.html
http://itpro.nikkeibp.co.jp/article/NEWS/20091113/340428/

エディションが「Ultimate」「Premium」「Professional」の3種類
価格が
* Ultimate with MSDN:新規購入価格は1万1924ドル、アップグレードは3841ドル
* Premium with MSDN:新規は5469ドル、アップグレードは2299ドル
* Professional with MSDN:新規は1199ドル、アップグレードは799ドル
* Professional without MSDN:799ドル

MSDN 無しのProfessional はアップグレードないの?

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

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) でも落ちました。

今でこそ MSBUILD や VCBUILD といった便利なツールがあるんだけど、Visual Studio .net 2003 にはそれがない。
何か無いかなと調べてたら devenv.com でできるらしい。別に変なサイト名とかではない。

使い方は簡単で、下記のような感じ
VS2003_DIRECTORY/Common7/IDE/devenv.com hoge.sln /build debug

これは hoge.sln を構成 debug ビルドするコマンド。
うん、簡単だ。VS2003 しかない場合でもこれを使えばコマンドラインで作業ができるね。

ちなみにこの devenv.com は vs2005 にも入ってる。使い方は同じ。
まぁ、2005から MSBUILD や VCBUILD があるので使われることは稀だと思う。。

環境変数に何も設定されていない状態で、

sh VC8_DIR/VC/vcpackages/vcbuild.exe PROJECT

としたら

Error: cannot locate vcbuildui.dll. Messages will not be localized.

と表示された。

でもビルドは正常にできている。
まぁ、dll 読めないから出力メッセージをローカライズできません ってエラーなので、特に問題ないんだけど。
日本語版だからメッセージは日本語でちゃんと出るので何も困らないし。

ちなみに VC9 だとこのメッセージ出ない。VC8 だけで出るっぽい?

つぃったーのタイムラインでも盛り上がってましたね(?)
Microsoft Pre-release Software Visual Studio 2010 and .NET Framework 4.0 Community Technology Preview (CTP)

自分も会社のPCにさっそく入れてみました。
導入手順はリンク先に全部載ってる&ログインパスワードも記載されてます。
ログインパスワードに気づかなくてどうやるのかなと少し悩んでました(((

せっかく入れたにも関わらず、仕事が忙しくて触れてません(TωT)
とりあえず キーバインド emacs を弄ってみたけど、まったく動かず。うぐぅ(DIO様)

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

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

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

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

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

前回は 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 の後に行うこと!
まぁ、当然っちゃ当然ですね。

ではまた次回!

バインドー、バインド。えぇ、いつもバインドボイスに悩まされます(MHP2G)

ってことで、今回はバインドしてみましょう。

いきなりソースですが、これは前回のソースをちょろちょろっと修正してるだけです。

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. class Hoge
  18. {
  19. public:
  20.     Hoge() : data_(1230) {}
  21.     explicit Hoge(int data) : data_(data) {}
  22.     ~Hoge() {}
  23.     void print() { std::cout <<data_ <<std::endl; }
  24.  
  25.     static void bind() {
  26.         SqPlus::SQClassDef<Hoge>(_T("Hoge")).
  27.             staticFunc(Hoge::constructHoge, _T("constructor")).
  28.             func(&Hoge::print, _T("print")).
  29.             var(&Hoge::data_, _T("data_"));
  30.     }
  31.  
  32.     static int constructHoge(int data, HSQUIRRELVM v) {
  33.         return SqPlus::PostConstruct<hoge>(v, new Hoge(data), SqPlus::ReleaseClassPtr</hoge><hoge>::release);
  34.     }
  35.  
  36. private:
  37.     int data_;
  38. };
  39.  
  40. int main(int argc, char** argv)
  41. {
  42.     SquirrelVM::Init();
  43.  
  44.     //----------------------------------------------------
  45.     // バインド
  46.     //----------------------------------------------------
  47.     // 変数
  48.     int   intValue   = 100;
  49.     float floatValue = 1.234f;
  50.     // 文字列は ScriptStringVar を使う
  51.     SqPlus::ScriptStringVar8 charValue = _T("hoge");
  52.  
  53.     // バインド
  54.     SqPlus::BindVariable(&intValue  , _T("intValue"));
  55.     SqPlus::BindVariable(&floatValue, _T("floatValue"));
  56.     SqPlus::BindVariable(&charValue , _T("charValue"));
  57.  
  58.  
  59.     //----------------------------------------------------
  60.     // Squirrel スクリプト側にクラスをバインド
  61.     //----------------------------------------------------
  62.     Hoge::bind();
  63.  
  64.  
  65.     //----------------------------------------------------
  66.     // スクリプトの読み込みとコンパイル
  67.     //----------------------------------------------------
  68.     SquirrelObject obj = SquirrelVM::CompileScript(_T("helloworld.nut"));
  69.  
  70.  
  71.     //----------------------------------------------------
  72.     // スクリプトの実行
  73.     //----------------------------------------------------
  74.     try {
  75.         SquirrelVM::RunScript(obj);
  76.     } catch (SquirrelError& e) {
  77.         // error 処理
  78.     }
  79.  
  80.     // 変更された後の値
  81.     std::cout <<"intValue = " <<intValue <<std::endl;
  82.  
  83.     SquirrelVM::Shutdown();
  84.  
  85.     return 0;
  86. }

C++:
  1. // helloworld.nut
  2. print("-- Begin SquirrelScript. --");
  3.  
  4. // 各種変数
  5. print("intValue   = " + intValue);
  6. print("floatValue = " + floatValue);
  7. print("charValue  = " + charValue);
  8.  
  9. // データ更新してみる
  10. intValue += 23;
  11.  
  12. // classValue
  13. local hoge = Hoge(2);
  14. hoge.print();
  15.  
  16. print("-- End SquirrelScript. --");


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

実行結果

-- Begin SquirrelScript. --
intValue = 100
floatValue = 1.234
charValue = hoge
2
-- End SquirrelScript. --
intValue = 123

まぁ、予想通りだと思います。
今回特殊なのはこれ。 Hoge::bind() の中で呼び出している staticFunc(Hoge::constructHoge, _T("constructor"))
Squirrel では引数付きコンストラクタはこのような形で登録してやらないと呼び出せない。
デフォルトコンストラクタとデストラクタについては、登録しなくても自動的に登録される。
# なぜか引数付きコンストラクタを登録すると、デフォルトコンストラクタが呼び出せなくなってしまう。

ではまた次回!次は Squirrel 側の関数を C++側から呼び出す方法などやりますかね。