19
C++で開発されるゲームのための RTTIを使用しない高速な Reflection(仮) (ソースもあるよ) 株式会社KH2O 大前広樹(@pigeon6) Saturday, October 9, 2010

Nadec magicreflection 20101009

Embed Size (px)

Citation preview

Page 1: Nadec magicreflection 20101009

C++で開発されるゲームのためのRTTIを使用しない高速な

Reflection(仮)(ソースもあるよ)

株式会社KH2O 大前広樹(@pigeon6)

Saturday, October 9, 2010

Page 2: Nadec magicreflection 20101009

Reflectionとは

Saturday, October 9, 2010

Page 3: Nadec magicreflection 20101009

Reflectionとは

Saturday, October 9, 2010

Page 4: Nadec magicreflection 20101009

Reflectionとはグラフィックの話ではありません

Saturday, October 9, 2010

Page 5: Nadec magicreflection 20101009

Reflectionとはグラフィックの話ではありません

プログラムの実行過程でプログラム自身の構造を読み取ったり書き換えたりする技術のこと(Wikipedia)

Saturday, October 9, 2010

Page 6: Nadec magicreflection 20101009

Reflectionが提供するもの

型(クラス)の情報を取得する

ある型が別の型にキャスト可能かを調べる

ある型のインスタンスを型名をキーに生成する

型が実装しているメソッドについて調べる

メソッドの引数について調べる

実際にそのメソッドを呼ぶ

こんな事が出来たら素敵かつ強力だぜ!

(そしてメタプログラミングは楽しいぜ!)

Saturday, October 9, 2010

Page 7: Nadec magicreflection 20101009

Reflectionが(C/C++ゲーム開発現場界隈で)あまりメジャーでない理由知らない・使ったことがない人が多い

boost的なライブラリが存在していない

遅い(JavaやC#のReflectionのイメージ)

メタ的なプログラムばかりになるので生産している気にならん

Saturday, October 9, 2010

Page 8: Nadec magicreflection 20101009

Reflectionが(C/C++ゲーム開発現場界隈で)あまりメジャーでない理由知らない・使ったことがない人が多い

boost的なライブラリが存在していない

遅い(JavaやC#のReflectionのイメージ)

メタ的なプログラムばかりになるので生産している気にならん

人生を損していますね!Saturday, October 9, 2010

Page 9: Nadec magicreflection 20101009

Saturday, October 9, 2010

Page 10: Nadec magicreflection 20101009

そんなあなたに、今回ご紹介するのが・・

Saturday, October 9, 2010

Page 11: Nadec magicreflection 20101009

そんなあなたに、今回ご紹介するのが・・

マジックリフレクション

MagicReflection

Saturday, October 9, 2010

Page 12: Nadec magicreflection 20101009

そんなあなたに、今回ご紹介するのが・・

マジックリフレクション

一家に一台、これさえあれば何でも出来ちゃう優れものです!

MagicReflection

Saturday, October 9, 2010

Page 13: Nadec magicreflection 20101009

MagicReflection設計方針RTTIを使わない

理由:ゲーム機のコンパイラではRTTIスイッチは余計な地雷踏みそうで怖い/ハード初期での落とし穴回避/開発途中でスイッチを変えるのがハードルになる

型の調査(型id)、文字列からインスタンスの生成、ダイナミックキャスト、メソッドの検索、メソッドの実行といった一通りの機能を提供する

引数を伴うインスタンスの生成が可能である

メソッドやコンストラクタのオーバーロードに対応する

メソッドやコンストラクタの実行時に、C/C++で許される型の自動変換に対応する

とにかく速く動く、但し安全に動く(安全な失敗)

システムの初期化以外のタイミングで、メモリの動的確保をしない

メンバ情報、アノテーション、モディファイアなどの提供はしない(実用十分主義)

Saturday, October 9, 2010

Page 14: Nadec magicreflection 20101009

MagicReflection 型ID

型IDの取得はどのような型に対しても可能

型IDはRTTIのtypeidと違い、単なるpointer_int互換の数値

意図的にT * const と T*

を等価として扱っている

型ID取得のコード例:

BaseClass* pBase = new BaseClass(); BaseClass2* pBase2 = new BaseClass2(); Inherited* pInherited = new Inherited(); mr_typeid_t id = mr_typeid(pBase); mr_typeid_t id2 = mr_typeid_static<BaseClass>(); mr_typeid_t id3 = mr_typeid_static<BaseClass*>(); assert(id3!=0);

mr_typeid_t id4 = mr_typeid_static<int>();

Saturday, October 9, 2010

Page 15: Nadec magicreflection 20101009

MR ダイナミックキャストダイナミックキャストはダイナミック型定義した型でのみ利用可能

多重継承や仮想継承をサポートしない(dynamic_cast

互換ではない)

ほぼ定数速度で動作

ダイナミックキャストのコード例:@Headerclass BaseClass { const char *pString;public: MR_DECLARE_DYNAMIC(BaseClass); ...};class Inherited : public BaseClass {public: MR_DECLARE_DYNAMIC(Inherited); ...};

@CppMR_IMPLEMENT_DYNAMIC(BaseClass);MR_IMPLEMENT_DYNAMIC_SUBCLASS(Inherited, BaseClass);

実行例: BaseClass* pSrc = pInherited; Inherited* pDst = mr_dynamic_cast<Inherited>(pSrc);  Inherited* pDst = mr_fast_dynamic_cast<Inherited>(pSrc);

Saturday, October 9, 2010

Page 16: Nadec magicreflection 20101009

MR インスタンス生成クラス名からインスタンスを生成することが可能

任意のコンストラクタを使用したインスタンスの生成が可能

インスタンス生成のコード例:@Headerclass BaseClass { const char *pString;public: MR_DECLARE_DYNAMIC(BaseClass); BaseClass() :pString("Hello"){ } BaseClass(const char* str) : pString(str) { } ...};@CppMR_DEFINE_DYNAMIC_CONSTRUCTOR_0(BaseClass);MR_DEFINE_DYNAMIC_CONSTRUCTOR_1(BaseClass, const char*);

実行例: MRRuntimeConstructionContext rcc; const MRRuntimeClass* pRC =    MRRuntimeClass::ForName("BaseClass"); rcc.SetParameter(0, "Some Parameter");

MRDynamicPtr pObj = pRC->CreateInstance(); MRDynamicPtr pObj2 = pRC->CreateInstance(rcc); BaseClass* pBase1 = mr_dynamic_cast<BaseClass>(pObj); BaseClass* pBase2 = mr_dynamic_cast<BaseClass>(pObj2);

Saturday, October 9, 2010

Page 17: Nadec magicreflection 20101009

MR メソッドの検索と実行クラス名からインスタンスを生成することが可能

任意のコンストラクタを使用したインスタンスの生成が可能

インスタンス生成のコード例:@Headerclass BaseClass { ... void Print(void) { printf("BaseClass:%s\n", pString); } void Print(int x, float f) { printf("BaseClass:%s %d, %f\n", pString, x, f); }};@CppMR_DEFINE_DYNAMIC_METHOD_0(BaseClass, void, Print);MR_DEFINE_DYNAMIC_METHOD_2(BaseClass, void, Print, int, float);

実行例: MRRuntimeConstructionContext rcc; const MRRuntimeClass* pRC = MRRuntimeClass::ForName("BaseClass"); MRDynamicPtr pObj = pRC->CreateInstance(); const MRMethod* pMethod = pRC->FindMethod("Print"); MRMethodInvocationContext mic(pObj, pMethod);

rcc.SetParameter(0, 123); rcc.SetParameter(1, 123.456f);

bool result = mic.Invoke();

Saturday, October 9, 2010

Page 18: Nadec magicreflection 20101009

MagicReflection 用途スクリプト言語に対する汎用バインディングの実装(関数ごとに用意することが不要)

スクリプト言語でC++オブジェクトをそのまま扱うことが可能に(生成・メソッド呼び出し・破棄)

コードの変更なしで事後拡張可能なシステムの実装(Abstract Factory

pattern)。またそのようなシステムをファイルから設定可能に。

汎用的なシリアライザ・デシリアライザの実装。

汎用的なRPC/RMIの実装。

Saturday, October 9, 2010