#ifndef _SQUIRREL_VM_H_ #define _SQUIRREL_VM_H_ #include "SquirrelObject.h" struct SquirrelError { SquirrelError(); SquirrelError(const SQChar* s):desc(s){} const SQChar *desc; }; // This class can hold a reference to a SquirrelVM. It keeps a Squirrel ref // to the VM to protect it from being deleted while held. struct SquirrelVMSys { SquirrelVMSys() { } ~SquirrelVMSys(); void Set( HSQUIRRELVM v ); void Set( const SquirrelObject& ov ); void Reset( ){ _vm.Reset(); } SquirrelVMSys& operator = (HSQUIRRELVM v){ Set(v); return *this; } operator HSQUIRRELVM () const; protected: void PushRefVM(HSQUIRRELVM v); void PopRefVM(); SquirrelObject _vm; friend class SquirrelVM; }; // Notes on creating / destroying SquirrelVM:s: // // VM:s created through sq_open are special since they create a new // SQSharedState. That shared state is later shared by any new thread // or friend VM. sq_close can be used for closing VM:s created through // sq_open (but not for friend VMs). // // Using squirrel references in SquirrelVMSys and SquirrelVM, one must // make sure that these are all reset if one calls sq_close manually. // // When there are no more references to a VM, it is destroyed automatically, // but the shared state is not! For VM:s created by SquirrelVM, it keeps // a list of shared states it has created and will destroy them all on // app shutdown. class SquirrelVM { friend class SquirrelObject; friend struct SquirrelError; friend struct SquirrelVMSys; public: // If a VM is passed as arg here, Init will not alter it. Otherwise // a new VM is created and initialized. A squirrel reference is kept // while it is the current VM. static bool Init( HSQUIRRELVM v=NULL ); // Initialize with an externally created VM, without adding a ref // on it. NOTE: This may not be compatible with Set/GetVMSys as // we're just working with raw pointers here. static bool InitNoRef( HSQUIRRELVM v ); static BOOL IsInitialized(){return _VM == NULL?FALSE:TRUE;} static void Release(); // Release ref on VM and reset VM pointer static void Shutdown(){ Release(); } static void AppFinalShutdown(); // Call when finally shutting down app static BOOL Update(); //debugger and maybe GC later static SquirrelObject CompileScript(const SQChar *s); static SquirrelObject CompileBuffer(const SQChar *s,const SQChar * debugInfo=_SC("console_buffer")); static SquirrelObject RunScript(const SquirrelObject &o,SquirrelObject *_this = NULL); static void PrintFunc(HSQUIRRELVM v,const SQChar* s,...); static BOOL BeginCall(const SquirrelObject &func); static BOOL BeginCall(const SquirrelObject &func,SquirrelObject &_this); static void PushParam(const SquirrelObject &o); static void PushParam(const SQChar *s); static void PushParam(SQInteger n); static void PushParam(SQFloat f); static void PushParam(SQUserPointer up); static void PushParamNull(); static SquirrelObject EndCall(); static SquirrelObject CreateString(const SQChar *s); static SquirrelObject CreateTable(); static SquirrelObject CreateArray(int size); static SquirrelObject CreateInstance(SquirrelObject &oclass); // oclass is an existing class. Create an 'instance' (OT_INSTANCE) of oclass. static SquirrelObject CreateFunction(SQFUNCTION func); static SquirrelObject CreateUserData(int size); static const SquirrelObject &GetRootTable(); static HSQUIRRELVM GetVMPtr() { return _VM; } // The sandbox VM ptr is one which cannot access functions bound with // SqPlus. It is suitable for running non-trusted scripts that can only // access basic functionality. static void SetSandboxVMPtr(HSQUIRRELVM v) { _sandboxVM = v; } // SetSandboxVMPtr static HSQUIRRELVM GetSandboxVMPtr() { return _sandboxVM; } // GetSandboxVMPtr static void GetVMSys(SquirrelVMSys & vmSys) { vmSys.Set( _vm ); } // GetVMSys static void SetVMSys(const SquirrelVMSys & vmSys) { Release(); HSQUIRRELVM v = (HSQUIRRELVM)vmSys; if( v ) Init( v ); } // SetVMSys static void PushValue(INT val) { sq_pushinteger(_VM,val); } // PushValue static void PushValue(FLOAT val) { sq_pushfloat(_VM,val); } // PushValue static void PushValue(bool val) { // Compiler treats SQBool as INT. sq_pushbool(_VM,val); } // PushValue static void PushValue(SQChar * val) { sq_pushstring(_VM,val,-1); } // PushValue static void PushValue(SQUserPointer val) { sq_pushuserpointer(_VM,val); } // PushValue static void PushValue(const SQChar * val) { sq_pushstring(_VM,val,-1); } // PushValue static void PushObject(SquirrelObject & so) { sq_pushobject(_VM,so._o); } // PushObject static void Pop(SQInteger nelemstopop) { sq_pop(_VM,nelemstopop); } // Pop static void PushRootTable(void); // Create/bind a function on the table currently on the stack. static SquirrelObject CreateFunction(SQFUNCTION func,const SQChar * scriptFuncName,const SQChar * typeMask=0); // Create/bind a function on the table so. typeMask: standard Squirrel types plus: no typemask means no args, "*" means any type of args. static SquirrelObject CreateFunction(SquirrelObject & so,SQFUNCTION func,const SQChar * scriptFuncName,const SQChar * typeMask=0); // Create/bind a function to the root table. typeMask: standard Squirrel types plus: no typemask means no args, "*" means any type of args. static SquirrelObject CreateFunctionGlobal(SQFUNCTION func,const SQChar * scriptFuncName,const SQChar * typeMask=0); // This is a helper to correct a difference in referncing new VM:s in // ref counted versus garbage collected modes. NOTE: Only use after creating // a VM with: 1 - sq_open() 2 - Creating a ref to the VM (SquirrelObject) static void DropVMRefIfRefCounted( HSQUIRRELVM v ); private: static SquirrelObject _vm; // This is a Squirrel reference to the VM static HSQUIRRELVM _VM; // The raw C++ pointer static bool _no_vm_ref; // Set if we only keep the raw C++ pointer and no ref static int _CallState; static SquirrelObject * _root; // Cached root table if non NULL static HSQUIRRELVM _sandboxVM; // The sandbox VM (that cannot use bound functions) }; template inline BOOL SquirrelObject::ArrayAppend(T item) { sq_pushobject(SquirrelVM::_VM,GetObjectHandle()); SquirrelVM::PushValue(item); BOOL res = sq_arrayappend(SquirrelVM::_VM,-2) == SQ_OK; sq_pop(SquirrelVM::_VM,1); return res; } // ArrayAppend #endif //_SQUIRREL_VM_H_