// SqPlusSmartPointer.h // SqPlus smart pointer member function support created by James Whitworth. // Modular integration 07/11/07 James Whitworth. // you must define the function: // unsigned char* getSmartPointerPointee(unsigned char*) { // return &(MySmartPointer->pointee); // } // somewhere in your program so it can correctly lookup member variables on the class pointed to // by your smart pointer. #ifdef SQPLUS_SMARTPOINTER_ACCESSTYPE #undef SQPLUS_SMARTPOINTER_ACCESSTYPE enum VarAccessType {VAR_ACCESS_READ_WRITE=0,VAR_ACCESS_READ_ONLY=1<<0,VAR_ACCESS_CONSTANT=1<<1,VAR_ACCESS_STATIC=1<<2,VAR_ACCESS_SMARTPOINTER=1<<3}; #endif // #ifdef SQPLUS_SMARTPOINTER_ACCESSTYPE #ifdef SQPLUS_SMARTPOINTER_REGISTER_VARIABLE #undef SQPLUS_SMARTPOINTER_REGISTER_VARIABLE // classType is the type of the member variable's containing class. template void RegisterSmartInstanceVariable(SquirrelObject & so, ClassTypeBase *classType, T *var, const SQChar *scriptVarName, VarAccessType access = VAR_ACCESS_READ_WRITE) { VarRef *pvr = createVarRef(so,scriptVarName); // var must be passed in as &obj->var, where obj = 0 // (the address is the offset), or as static/global address. void *offsetOrAddrOrConst = static_cast(var); *pvr = VarRef(offsetOrAddrOrConst, TypeInfo(), classType, ClassType::type(), sizeof(*var), access); pvr->m_access |= VAR_ACCESS_SMARTPOINTER; createInstanceSetGetHandlers(so); } #endif // #ifdef SQPLUS_SMARTPOINTER_REGISTER_VARIABLE #ifdef SQPLUS_SMARTPOINTER_DISPATCH #undef SQPLUS_SMARTPOINTER_DISPATCH template class DirectCallSmartInstanceMemberFunction { public: static inline int Dispatch(HSQUIRRELVM v) { DirectCallInstanceFuncPicker p(v); if (!p.instance || !p.func) { sq_throwerror(v, _SC("Invalid Instance Type")); } Pointee *pointeeInstance = static_cast(p.instance->get()); return !pointeeInstance ? sq_throwerror(v, _SC("SmartPointer Pointee NULL")) : Call(*pointeeInstance, *(p.func), v, 2); } }; #endif // #ifdef SQPLUS_SMARTPOINTER_DISPATCH #ifdef SQPLUS_SMARTPOINTER_DIRECT_CLOSURE #undef SQPLUS_SMARTPOINTER_DIRECT_CLOSURE template inline void sq_pushdirectsmartinstanceclosure(HSQUIRRELVM v,const Callee & callee,const Pointee & pointee,Func func,SQUnsignedInteger nupvalues) { unsigned char * up = (unsigned char *)sq_newuserdata(v,sizeof(func)); // Also pushed on stack. memcpy(up,&func,sizeof(func)); sq_newclosure(v,DirectCallSmartInstanceMemberFunction::Dispatch,nupvalues+1); } // sq_pushdirectinstanceclosure #endif // #ifdef SQPLUS_SMARTPOINTER_DIRECT_CLOSURE #ifdef SQPLUS_SMARTPOINTER_REGISTER_INSTANCE #undef SQPLUS_SMARTPOINTER_REGISTER_INSTANCE template inline void RegisterSmartInstance(HSQUIRRELVM v,HSQOBJECT hclass,Callee & callee,Pointee & pointee,Func func,const SQChar * name) { sq_pushobject(v,hclass); sq_pushstring(v,name,-1); sq_pushdirectsmartinstanceclosure(v,callee,pointee,func,0); sq_createslot(v,-3); sq_poptop(v); // Remove hclass. } // RegisterInstance #endif // #ifdef SQPLUS_SMARTPOINTER_REGISTER_INSTANCE #ifdef SQPLUS_SMARTPOINTER_CLASS_DEF_FUNC #undef SQPLUS_SMARTPOINTER_CLASS_DEF_FUNC // Register a smartpointer member function. template SQClassDefBase & smartFunc(Func pfunc,const SQChar * name) { RegisterSmartInstance(v,newClass.GetObjectHandle(),*(TClassType *)0,*(Pointee *)0,pfunc,name); return *this; } // func #endif // #ifdef SQPLUS_SMARTPOINTER_CLASS_DEF_FUNC #ifdef SQPLUS_SMARTPOINTER_CLASS_DEF_VAR #undef SQPLUS_SMARTPOINTER_CLASS_DEF_VAR // Register a member variable. template SQClassDefBase & smartVar(VarType Pointee::* pvar,const SQChar * name,VarAccessType access=VAR_ACCESS_READ_WRITE) { struct CV { VarType Pointee::* var; } cv; // Cast Variable helper. cv.var = pvar; RegisterSmartInstanceVariable(newClass,ClassType::type(),*(VarType **)&cv,name,access); return *this; } // var // Register a member variable as a UserPointer (read only). template SQClassDefBase & smartVarAsUserPointer(VarType Pointee::* pvar,const SQChar * name) { struct CV { VarType Pointee::* var; } cv; // Cast Variable helper. cv.var = pvar; RegisterSmartInstanceVariable(newClass,ClassType::type(),*(SQAnything **)&cv,name,VAR_ACCESS_READ_ONLY); return *this; } // varAsUserPointer #endif // #ifdef SQPLUS_SMARTPOINTER_CLASS_DEF_VAR #ifdef SQPLUS_SMARTPOINTER_CPP_DECLARATION #undef SQPLUS_SMARTPOINTER_CPP_DECLARATION extern unsigned char* getSmartPointerPointee(unsigned char*); #endif #ifdef SQPLUS_SMARTPOINTER_INSTANCE_VARINFO #undef SQPLUS_SMARTPOINTER_INSTANCE_VARINFO if(vr->m_access & VAR_ACCESS_SMARTPOINTER) { up = reinterpret_cast( getSmartPointerPointee(reinterpret_cast(up)) ); } #endif // #ifdef SQPLUS_SMARTPOINTER_CPP_DECLARATION // SqPlusSmartPointer.h