C++インスタンス関数を呼び出すSquirrelインスタンス関数(マイフェイバリットな)
SQPlusはC++のインスタンスをinstanceupへ、関数ポインタをfunctionのfree variableへいれてる。free variable分はいらなくないか?と思ったので。自分はこんなふうに書いた。テンプレートってホント融通きくなあ。
inline static void mysq_register_function(HSQUIRRELVM v, const char* name, SQFUNCTION func, int numparams, const char* paramtype, SQBool bstatic = SQFalse) { sq_pushstring(v,name,-1); sq_newclosure(v,func,0); if(paramtype) sq_setparamscheck(v,numparams,paramtype); sq_setnativeclosurename(v,-1,name); sq_newslot(v,-3,bstatic); } template <typename T, int(T::*FUNC)(HSQUIRRELVM)> static int _mysq_instance_nativeclosure(HSQUIRRELVM v) { T* g = (T*)_instance(stack_get(v,1))->_userpointer; return (g->*FUNC)(v); } #define MYSQ_REG_INSTANCE_LINKED_FUNCTION(VM,CLASS,FUNCNAME,PNUM,FORMAT) \ mysq_register_function(VM,#FUNCNAME,_mysq_instance_nativeclosure<CLASS,&CLASS::FUNCNAME>,PNUM,FORMAT)
で、こんな風に使える。
SQObjectPtr sqclass; _table(v->_roottable)->Get(SQObjectPtr(SQString::Create(_ss(v),"Agent")),sqclass); sq_pushobject(v,sqclass); MYSQ_REG_INSTANCE_LINKED_FUNCTION(v,MobBotWithAI,WalkTo, 2, ".x"); MYSQ_REG_INSTANCE_LINKED_FUNCTION(v,MobBotWithAI,Attack, 0, ".ix"); MYSQ_REG_INSTANCE_LINKED_FUNCTION(v,MobBotWithAI,Track, 2, ".x"); sq_poptop(v);
Squirrelのインスタンスをつくるときは紐付けるC++のインスタンスをsq_setinstanceupすることを忘れずに
mysq_call(v,true,-1,"Agent"); m_sqagent = stack_get(v,-1); // C++ -> Squirrel の参照 _instance(m_sqagent)->_userpointer = this; // C++ <- Squirrel の参照
最近はできるだけスタックを使わないのがマイブーム。