// testSqPlus.cpp // Created by John Schultz 9/5/2005 // Free for any use. #include #include #include "sqplus.h" using namespace SqPlus; struct CTestObj { float x; float y; float z; CTestObj() { x = y = z = 0.f; } void update(float t) { x += t; } // update void print(void) { SQChar buff[256]; scsprintf(buff,_SC("x: %f\n"),x); // OutputDebugString(buff); SCPUTS(buff); } // print }; _DECL_CLASS(TestObj); _IMPL_NATIVE_CONSTRUCTION(TestObj,CTestObj); _MEMBER_FUNCTION_IMPL(TestObj,constructor) { CTestObj * newv = NULL; StackHandler sa(v); int nparams = sa.GetParamCount(); newv = new CTestObj(); return construct_TestObj(newv); } _MEMBER_FUNCTION_IMPL(TestObj,_set) { StackHandler sa(v); _CHECK_SELF(CTestObj,TestObj); const SQChar *s = sa.GetString(2); int index = s?s[0]:sa.GetInt(2); switch(index) { case 0: case 'x': case 'r': return sa.Return(self->x = sa.GetFloat(3)); break; case 1: case 'y': case 'g': return sa.Return(self->y = sa.GetFloat(3)); break; case 2: case 'z': case 'b': return sa.Return(self->z = sa.GetFloat(3)); break; } // switch return SQ_ERROR; } _MEMBER_FUNCTION_IMPL(TestObj,_get) { StackHandler sa(v); _CHECK_SELF(CTestObj,TestObj); const SQChar *s = sa.GetString(2); if(s && (s[1] != 0)) return SQ_ERROR; int index = s && (s[1] == 0)?s[0]:sa.GetInt(2); switch(index) { case 0: case 'x': case 'r': return sa.Return(self->x); break; case 1: case 'y': case 'g': return sa.Return(self->y); break; case 2: case 'z': case 'b': return sa.Return(self->z); break; } // switch return SQ_ERROR; } _MEMBER_FUNCTION_IMPL(TestObj,update) { StackHandler sa(v); _CHECK_SELF(CTestObj,TestObj); SQObjectType type = (SQObjectType)sa.GetType(2); if (type == OT_FLOAT || type == OT_INTEGER) { float t = sa.GetFloat(2); self->update(t); } else { SQChar buff[256]; scsprintf(buff,_SC("Invalid type for CTestObj::update(float): type %d\n"),type); // OutputDebugString(buff); SCPUTS(buff); } // if return SQ_OK;; } _MEMBER_FUNCTION_IMPL(TestObj,print) { StackHandler sa(v); _CHECK_SELF(CTestObj,TestObj); SQChar buff[256]; scsprintf(buff,_SC("x: %f y: %f z: %f\n"),self->x,self->y,self->z); // OutputDebugString(buff); SCPUTS(buff); // return sa.ThrowError(_SC("Error initializing the device")); return SQ_OK;; } _MEMBER_FUNCTION_IMPL(TestObj,_print) { _CHECK_SELF(CTestObj,TestObj); SCPUTS(_SC("_print: ")); return __TestObj_print(v); } _BEGIN_CLASS(TestObj) _MEMBER_FUNCTION(TestObj,constructor,1,_SC("x")) // x = instance ('self/this' not yet created), no arguments. _MEMBER_FUNCTION(TestObj,_set,3,_SC("xs|n")) // x = instance, string, or int/float, as .x, .y, .z, or [0], [1], [2]. _MEMBER_FUNCTION(TestObj,_get,2,_SC("xs|n")) // x = instance, string, or int/float, as .x, .y, .z, or [0], [1], [2]. _MEMBER_FUNCTION(TestObj,update,2,_SC("xn")) // x = instance (this), n = int or float. _MEMBER_FUNCTION(TestObj,print,1,_SC("x")) // x = instance (this). _MEMBER_FUNCTION(TestObj,_print,1,_SC("x")) // x = instance (this). _END_CLASS(TestObj) #ifdef SQUNICODE #define scvprintf vwprintf #else #define scvprintf vprintf #endif void printfunc(HSQUIRRELVM v,const SQChar *s,...) { va_list arglist; va_start(arglist, s); scvprintf(s, arglist); va_end(arglist); } int testFunc(HSQUIRRELVM v) { StackHandler sa(v); int paramCount = sa.GetParamCount(); scprintf(_SC("testFunc: numParams[%d]\n"),paramCount); for (int i=1; i <= paramCount; i++) { scprintf(_SC("param[%d]: "),i); switch(sa.GetType(i)) { case OT_TABLE: scprintf(_SC("OT_TABLE[0x%x]\n"),sa.GetObjectHandle(i)); break; case OT_INTEGER: scprintf(_SC("OT_INTEGER[%d]\n"),sa.GetInt(i)); break; case OT_FLOAT: scprintf(_SC("OT_FLOAT[%f]\n"),sa.GetFloat(i)); break; case OT_STRING: scprintf(_SC("OT_STRING[%s]\n"),sa.GetString(i)); break; default: scprintf(_SC("TYPEID[%d]\n"),sa.GetType(i)); } // switch } // for return SQ_OK; } // testFunc // === BEGIN User Pointer version === #if 0 int setVarFunc2(HSQUIRRELVM v) { StackHandler sa(v); if (sa.GetType(1) == OT_TABLE) { HSQOBJECT htable = sa.GetObjectHandle(1); SquirrelObject table(htable); const SQChar * el = sa.GetString(2); SquirrelObject upValMapPtr = table.GetValue(_SC("_uvp")); SquirrelObject upValMapType = table.GetValue(_SC("_uvt")); if (!upValMapType.Exists(el)) { return SQ_ERROR; } // if int vType = upValMapType.GetInt(el); switch (vType) { case TypeInfo::TypeID: { int * val = (int *)upValMapPtr.GetUserPointer(el); if (val) { *val = sa.GetInt(3); return sa.Return(*val); } else { return sa.Return(-1); } // if } // case case TypeInfo::TypeID: { float * val = (float *)upValMapPtr.GetUserPointer(el); if (val) { *val = sa.GetFloat(3); return sa.Return(*val); } else { return sa.Return(-1); } // if } // case case TypeInfo::TypeID: { bool * val = (bool *)upValMapPtr.GetUserPointer(el); if (val) { *val = sa.GetBool(3) ? true : false; return sa.Return(*val); } else { return sa.Return(-1); } // if } // case } // switch } // if return SQ_ERROR; } // setVarFunc2 int getVarFunc2(HSQUIRRELVM v) { StackHandler sa(v); if (sa.GetType(1) == OT_TABLE) { HSQOBJECT htable = sa.GetObjectHandle(1); SquirrelObject table(htable); int type = sa.GetType(2); const SQChar * el = sa.GetString(2); SquirrelObject upValMap = table.GetValue(_SC("_uvp")); SquirrelObject upValMapType = table.GetValue(_SC("_uvt")); if (!upValMapType.Exists(el)) { return SQ_ERROR; } // if int vType = upValMapType.GetInt(el); switch (vType) { case TypeInfo::TypeID: { int * val = (int *)upValMap.GetUserPointer(el); if (val) { return sa.Return(*val); } else { return sa.Return(-1); } // if } // case case TypeInfo::TypeID: { float * val = (float *)upValMap.GetUserPointer(el); if (val) { return sa.Return(*val); } else { return sa.Return(-1); } // if } // case case TypeInfo::TypeID: { bool * val = (bool *)upValMap.GetUserPointer(el); if (val) { return sa.Return(*val); } else { return sa.Return(-1); } // if } // case } // switch } // if return SQ_ERROR; } // getVarFunc2 template void bindVariable2(SquirrelObject & so,T & var,const SQChar * scriptVarName) { SquirrelObject __upValMapPtr; SquirrelObject __upValMapType; if (so.Exists(_SC("_uvp"))) { __upValMapPtr = so.GetValue(_SC("_uvp")); __upValMapType = so.GetValue(_SC("_uvt")); } else { __upValMapPtr = SquirrelVM::CreateTable(); __upValMapType = SquirrelVM::CreateTable(); } // if int varType = TypeInfo::TypeID; __upValMapPtr.SetUserPointer(scriptVarName,&var); __upValMapType.SetValue(scriptVarName,varType); so.SetValue(_SC("_uvp"),__upValMapPtr); so.SetValue(_SC("_uvt"),__upValMapType); SquirrelObject delegate = so.GetDelegate(); if (!delegate.Exists(_SC("_set"))) { delegate = SquirrelVM::CreateTable(); SquirrelVM::CreateFunction(delegate,"_set",setVarFunc2,_SC("sn|b")); // String var name = number(int or float) or bool. SquirrelVM::CreateFunction(delegate,"_get",getVarFunc2,_SC("s")); // String var name. so.SetDelegate(delegate); } // if } // bindVariable2 #endif // === BEGIN Old, initial test versions. === int setIntFunc(HSQUIRRELVM v) { StackHandler sa(v); if (sa.GetType(1) == OT_TABLE) { HSQOBJECT htable = sa.GetObjectHandle(1); SquirrelObject table(htable); const SQChar * el = sa.GetString(2); SquirrelObject upValMap = table.GetValue(_SC("upValMap")); int * val = (int *)upValMap.GetUserPointer(el); if (val) { *val = sa.GetInt(3); return sa.Return(*val); } else { return sa.Return(-1); } // if } // if return SQ_ERROR; } // setIntFunc int getIntFunc(HSQUIRRELVM v) { StackHandler sa(v); if (sa.GetType(1) == OT_TABLE) { HSQOBJECT htable = sa.GetObjectHandle(1); SquirrelObject table(htable); int type = sa.GetType(2); const SQChar * el = sa.GetString(2); SquirrelObject upValMap = table.GetValue(_SC("upValMap")); int * val = (int *)upValMap.GetUserPointer(el); if (val) { return sa.Return(*val); } else { return sa.Return(-1); } // if } // if return SQ_ERROR; } // getIntFunc // === END Old, initial tests versions. === _DECL_STATIC_NAMESPACE(GB); // Globals _MEMBER_FUNCTION_IMPL(GB,Update) { StackHandler sa(v); scprintf(_SC("GB.Update()\n")); return sa.Return(true); } enum {TEST_CONST=123}; _BEGIN_NAMESPACE(GB) _MEMBER_FUNCTION(GB,Update,0,0) _BEGIN_NAMESPACE_CONSTANTS(GB) _CONSTANT_IMPL(TEST_CONST,OT_INTEGER) _END_NAMESPACE(GB,NULL) #if 0 int getVarName(HSQUIRRELVM v) { StackHandler sa(v); const SQChar * varName = sq_getlocal(v,1,0); return sa.Return(varName); } // getVarName #endif void newtest(void) { scprintf(_SC("NewTest\n")); } SQChar * newtestR1(const SQChar * inString) { scprintf(_SC("NewTestR1: %s\n"),inString); return _SC("Returned String"); } struct NewTestObj { ScriptStringVar64 s1; ScriptStringVar32 s2; int pad; int val; int c1; ScriptStringVar8 c2; // 8 char plus null (max string is 8 printable chars). NewTestObj() : val(777) { s1 = _SC("s1"); s2 = _SC("s2"); c1 = 996; c2 = _SC("It's a 997"); // Prints: "It's a 9", as only 8 chars in static buffer (plus null). } void newtest(void) { scprintf(_SC("NewTest: %d\n"),val); } SQChar * newtestR1(const SQChar * inString) { scprintf(_SC("NewTestR1: Member var val is %d, function arg is %s\n"),val,inString); return _SC("Returned String"); } int multiArgs(HSQUIRRELVM v) { StackHandler sa(v); int paramCount = sa.GetParamCount(); int p1 = sa.GetInt(2); int p2 = sa.GetInt(3); int p3 = sa.GetInt(4); return 0; } // multiArgs int _set(HSQUIRRELVM v) { StackHandler sa(v); int paramCount = sa.GetParamCount(); const SQChar * el = sa.GetString(2); val = sa.GetInt(3); return sa.Return(val); // return setInstanceVarFunc(v); } int _get(HSQUIRRELVM v) { StackHandler sa(v); int paramCount = sa.GetParamCount(); // return getInstanceVarFunc(v); return sa.Return(val); } }; struct CustomTestObj { ScriptStringVar128 name; int val; bool state; CustomTestObj() : val(0), state(false) { name = _SC("empty"); } CustomTestObj(const SQChar * _name,int _val,bool _state) : val(_val), state(_state) { name = _name; } static int construct(HSQUIRRELVM v) { StackHandler sa(v); int paramCount = sa.GetParamCount(); if (paramCount == 1) { return PostConstruct(v,new CustomTestObj(),release); } if (paramCount == 4) { return PostConstruct(v,new CustomTestObj(sa.GetString(2),sa.GetInt(3),sa.GetBool(4)?true:false),release); } // if return sq_throwerror(v,_SC("Invalid Constructor arguments")); } // construct SQ_DECLARE_RELEASE(CustomTestObj) // Member function that handles variable types. int varArgTypes(HSQUIRRELVM v) { StackHandler sa(v); int paramCount = sa.GetParamCount(); if (sa.GetType(2) == OT_INTEGER) { val = sa.GetInt(2); } // if if (sa.GetType(2) == OT_STRING) { name = sa.GetString(2); } // if if (sa.GetType(3) == OT_INTEGER) { val = sa.GetInt(3); } // if if (sa.GetType(3) == OT_STRING) { name = sa.GetString(3); } // if return 0; } // varArgTypes // Member function that handles variable types and has variable return types+count. int varArgTypesAndCount(HSQUIRRELVM v) { StackHandler sa(v); int paramCount = sa.GetParamCount(); SQObjectType type1 = (SQObjectType)sa.GetType(1); // Always OT_INSTANCE SQObjectType type2 = (SQObjectType)sa.GetType(2); SQObjectType type3 = (SQObjectType)sa.GetType(3); SQObjectType type4 = (SQObjectType)sa.GetType(4); int returnCount = 0; if (paramCount == 3) { sq_pushinteger(v,val); returnCount = 1; } else if (paramCount == 4) { sq_pushinteger(v,val); sq_pushstring(v,name,-1); returnCount = 2; } // if return returnCount; } // int noArgsVariableReturn(HSQUIRRELVM v) { if (val == 123) { val++; return 0; // This will print (null). } else if (val == 124) { sq_pushinteger(v,val); // Will return int:124. val++; return 1; } else if (val == 125) { sq_pushinteger(v,val); name = _SC("Case 125"); sq_pushstring(v,name,-1); val = 123; // reset return 2; } // if return 0; } // noArgsVariableReturn // Registered with func() instead of funcVarArgs(): fixed (single) return type. const SQChar * variableArgsFixedReturnType(HSQUIRRELVM v) { StackHandler sa(v); int paramCount = sa.GetParamCount(); SQObjectType type1 = (SQObjectType)sa.GetType(1); // Always OT_INSTANCE SQObjectType type2 = (SQObjectType)sa.GetType(2); SQObjectType type3 = (SQObjectType)sa.GetType(3); if (paramCount == 1) { return _SC("No Args"); } else if (paramCount == 2) { return _SC("One Arg"); } else if (paramCount == 3) { return _SC("Two Args"); } // if return _SC("More than two args"); } // variableArgsFixedReturnType void manyArgs(int i,float f,bool b,const SQChar * s) { scprintf(_SC("i: %d, f: %f, b: %s, s: %s\n"),i,f,b?_SC("true"):_SC("false"),s); } // manyArgs float manyArgsR1(int i,float f,bool b,const SQChar * s) { manyArgs(i,f,b,s); return i+f; } // manyArgsR1 }; #if 0 struct Base { int val1; ScriptStringVar16 nameBase; Base() : nameBase(_SC("Base")) { val1 = 123; } void funcBase(void) { scprintf(_SC("Val1: %d, Name: %s\n"),val1,nameBase.s); } }; struct Derived { int val2; ScriptStringVar16 nameDerived; Derived() : nameDerived(_SC("Derived")), val2(456) { val2 = 456; } void funcDerived(void) { scprintf(_SC("Val2: %d, Name: %s\n"),val2,nameDerived.s); } }; #endif //SQ_DECLARE_CLASS(NewTestObj); class TestSqPlus { public: void init(void) { SquirrelVM::Init(); // sq_setprintfunc(SquirrelVM::GetVMPtr(),printfunc); //sets the print function. _INIT_CLASS(TestObj); _INIT_STATIC_NAMESPACE(GB); } // if TestSqPlus() { init(); try { HSQUIRRELVM v = SquirrelVM::GetVMPtr(); // === BEGIN Global Function binding tests === // Implemented as SquirrelVM::CreateFunction(rootTable,func,name,typeMask); SquirrelVM::CreateFunctionGlobal(&testFunc,_SC("testFunc0")); SquirrelVM::CreateFunctionGlobal(&testFunc,_SC("testFuncN"),_SC("n")); SquirrelVM::CreateFunctionGlobal(&testFunc,_SC("testFuncS"),_SC("s")); // === Register Standard Functions === RegisterGlobal(v,&newtest,_SC("test")); RegisterGlobal(v,&newtestR1,_SC("testR1")); // === Register Member Functions to existing classes (as opposed to instances of classes) === NewTestObj t1,t2,t3; t1.val = 123; t2.val = 456; t3.val = 789; RegisterGlobal(v,t1,&NewTestObj::newtest,_SC("testObj_newtest1")); RegisterGlobal(v,t2,&NewTestObj::newtest,_SC("testObj_newtest2")); // Register newtest() again with different name and object pointer. SquirrelObject tr = SquirrelVM::GetRootTable(); // Can be any object supporting closures (functions). Register(v,tr.GetObjectHandle(),t3,&NewTestObj::newtestR1,_SC("testObj_newtestR1")); // Return value version. // === END Global Function binding tests === // === BEGIN Class Instance tests === #if 0 SQClassDef sqClass(_SC("NewTestObj")); sqClass.func(&NewTestObj::newtestR1,_SC("newtestR1")); sqClass.var(&NewTestObj::val,_SC("val")); sqClass.var(&NewTestObj::s1,_SC("s1")); sqClass.var(&NewTestObj::s2,_SC("s2")); sqClass.var(&NewTestObj::c1,_SC("c1"),VAR_ACCESS_READ_ONLY); sqClass.var(&NewTestObj::c2,_SC("c2"),VAR_ACCESS_READ_ONLY); sqClass.funcVarArgs(&NewTestObj::multiArgs,_SC("multiArgs")); #else SQClassDef(_SC("NewTestObj")). func(&NewTestObj::newtestR1,_SC("newtestR1")). var(&NewTestObj::val,_SC("val")). var(&NewTestObj::s1,_SC("s1")). var(&NewTestObj::s2,_SC("s2")). var(&NewTestObj::c1,_SC("c1"),VAR_ACCESS_READ_ONLY). var(&NewTestObj::c2,_SC("c2"),VAR_ACCESS_READ_ONLY). funcVarArgs(&NewTestObj::multiArgs,_SC("multiArgs")); #endif SQClassDef customClass(_SC("CustomTestObj")); customClass.staticFuncVarArgs(&CustomTestObj::construct,_SC("constructor"),_SC("snb")); // string, number, bool (all types must match). customClass.funcVarArgs(&CustomTestObj::varArgTypes,_SC("varArgTypes"),_SC("s|ns|ns|ns|n")); // string or number + string or number. customClass.funcVarArgs(&CustomTestObj::varArgTypesAndCount,_SC("varArgTypesAndCount"),_SC("*")); // "*"): no type or count checking. customClass.funcVarArgs(&CustomTestObj::noArgsVariableReturn,_SC("noArgsVariableReturn")); // No type string means no arguments allowed. customClass.func(&CustomTestObj::variableArgsFixedReturnType,_SC("variableArgsFixedReturnType")); // Variables args, fixed return type. customClass.func(&CustomTestObj::manyArgs,_SC("manyArgs")); // Many args, type checked. customClass.func(&CustomTestObj::manyArgsR1,_SC("manyArgsR1")); // Many args, type checked, one return value. // Old macro-based method. Must use SQ_DECLARE_CLASS() macro above. #if 0 SquirrelObject newClass = SQ_REGISTER_CLASS(NewTestObj); SQ_REGISTER_INSTANCE(newClass,NewTestObj,newtestR1); // Currently, can use either automatic variable handling OR manual handling (but not both at once). #if 1 SQ_REGISTER_INSTANCE_VARIABLE(newClass,NewTestObj,val); // _set/_get will be defined to use automatic methods for val. #else SQ_REGISTER_INSTANCE_VARARGS(newClass,NewTestObj,_set); // _set is now defined and won't be overridden. SQ_REGISTER_INSTANCE_VARARGS(newClass,NewTestObj,_get); SQ_REGISTER_INSTANCE_VARIABLE(newClass,NewTestObj,val); // Access will be through _set/_get member functions above, not automatic methods. #endif #if 1 // With an HSQUIRRELVM argument, can handle variable args, and when registered this way can return multiple values. SQ_REGISTER_INSTANCE_VARARGS(newClass,NewTestObj,multiArgs); #else // With an HSQUIRRELVM argument, can handle variable args, but can only return one value (defined by the function definition). SQ_REGISTER_INSTANCE(newClass,NewTestObj,multiArgs); #endif #endif #if 1 SquirrelObject testReg0 = SquirrelVM::CompileBuffer(_SC(" co <- CustomTestObj(\"hello\",123,true); co.varArgTypes(\"str\",123,123,\"str\"); co.varArgTypes(123,\"str\",\"str\",123); ")); SquirrelVM::RunScript(testReg0); SquirrelObject testReg0a = SquirrelVM::CompileBuffer(_SC(" print(co.varArgTypesAndCount(1,true)); print(co.varArgTypesAndCount(2,false,3.)); print(\"\\n\"); ")); SquirrelVM::RunScript(testReg0a); SquirrelObject testReg0b = SquirrelVM::CompileBuffer(_SC(" print(co.noArgsVariableReturn()); print(co.noArgsVariableReturn()); print(co.noArgsVariableReturn()); print(\"\\n\"); ")); SquirrelVM::RunScript(testReg0b); SquirrelObject testReg0c = SquirrelVM::CompileBuffer(_SC(" print(co.variableArgsFixedReturnType(1)); print(co.variableArgsFixedReturnType(1,2)); print(co.variableArgsFixedReturnType(1,2,3)); print(\"\\n\"); ")); SquirrelVM::RunScript(testReg0c); SquirrelObject testReg0d = SquirrelVM::CompileBuffer(_SC(" co.manyArgs(111,222.2,true,\"Hello\"); print(co.manyArgsR1(333,444.3,false,\"World\")); print(\"\\n\"); ")); SquirrelVM::RunScript(testReg0d); #endif // Inheriting from an existing base class in this way is not currently supported. // Requires either a Squirrel language/behavior change, or extra code at the interface // layer to allocate memory and call constructor of parent class (and perhaps // handle constructor args) store pointer in UserData, and handle proper variable access // (get correct class/struct pointer) and member function calls (store class // type/id in function up-var and search/hash for actual 'this' pointer for function call). #if 0 SQClassDef(_SC("Base")). var(&Base::nameBase,_SC("nameBase")). func(&Base::funcBase,_SC("funcBase")); SQClassDef("Derived",_SC("Base")). var(&Derived::nameDerived,_SC("nameDerived")). func(&Derived::funcDerived,_SC("funcDerived")); // SquirrelObject testBaseDerived = SquirrelVM::CompileBuffer(_SC(" local base = Base(); print(base.nameBase); local derived = Derived(); print(\"NameBase: \"+derived.nameBase+\" NameDerived: \"+derived.nameDerived); derived.funcBase(); ")); SquirrelObject testBaseDerived = SquirrelVM::CompileBuffer(_SC(" local derived = Derived(); print(\"NameBase: \"+derived.nameBase+\" NameDerived: \"+derived.nameDerived); derived.funcBase(); ")); SquirrelVM::RunScript(testBaseDerived); #endif #if 1 SquirrelObject testReg1a = SquirrelVM::CompileBuffer(_SC(" co <- CustomTestObj(\"hello\",123,true); co.noArgsVariableReturn(); local t = NewTestObj(); print(\"C1: \"+t.c1); print(\"C2: \"+t.c2); // t.c1 = 123; ")); SquirrelVM::RunScript(testReg1a); // Constant test (read only var). Var can change on C++ side, but not on script side. try { SquirrelObject testRegConstant = SquirrelVM::CompileBuffer(_SC(" local t = NewTestObj(); t.c1 = 123; ")); SquirrelVM::RunScript(testRegConstant); } // try catch (SquirrelError & e) { SQChar buff[256]; scsprintf(buff,_SC("Error: %s, %s\n"),e.desc,_SC("Squirrel::TestConstant")); // OutputDebugString(buff); SCPUTS(buff); } // catch SquirrelObject testReg1 = SquirrelVM::CompileBuffer(_SC(" local t = NewTestObj(); t.newtestR1(\"Hello\"); t.val = 789; print(t.val); print(t.s1); print(t.s2); t.s1 = \"New S1\"; print(t.s1); ")); SquirrelVM::RunScript(testReg1); SquirrelObject testReg2 = SquirrelVM::CompileBuffer(_SC(" local t = NewTestObj(); t.val = 789; print(t.val); t.val = 876; print(t.val); t.multiArgs(1,2,3); t.multiArgs(1,2,3,4); ")); SquirrelVM::RunScript(testReg2); SquirrelObject testReg3 = SquirrelVM::CompileBuffer(_SC(" test(); local rv = testR1(\"Hello\"); print(rv); ")); SquirrelVM::RunScript(testReg3); SquirrelObject testReg4 = SquirrelVM::CompileBuffer(_SC(" print(\"\\nMembers:\"); testObj_newtest1(); testObj_newtest2(); print(testObj_newtestR1(\"Hello Again\")); ")); SquirrelVM::RunScript(testReg4); SquirrelObject defCallFunc = SquirrelVM::CompileBuffer(_SC(" function callMe(var) { print(\"I was called by: \"+var); return 123; }")); SquirrelVM::RunScript(defCallFunc); SquirrelObject root = SquirrelVM::GetRootTable(); // Get a function from the root table and call it. SquirrelFunction callFunc(_SC("callMe")); int ival = callFunc(_SC("Squirrel")); scprintf(_SC("IVal: %d\n"),ival); ival = 0; // Get a function from any table. SquirrelFunction callFunc2(root.GetObjectHandle(),_SC("callMe")); ival = callFunc(456); // Argument count is checked; type is not. // === END Class Instance tests === // === BEGIN macro-only class-registrated tests === // SquirrelVM::CreateFunctionGlobal(_SC("getName",getVarName,"*")); // * = any type. // SquirrelObject main = SquirrelVM::CompileBuffer(_SC("local testObj = TestObj(); testObj.print(); testObj.update(\"ab\"); testObj.print()")); // SquirrelObject main = SquirrelVM::CompileBuffer(_SC("local LF = \"\\n\"; local testObj = TestObj(); testObj.print(); testObj.update(1.5); testObj.print(); testObj.y += 10.; testObj.z = -1.; print(testObj.y+LF); print(\"Array: \"+testObj[0]+LF); print(testObj); print(LF); ")); // SquirrelObject main = SquirrelVM::CompileBuffer(_SC("local testObj = TestObj(); testObj.z = -1.; print(testObj); testFunc(); testFunc0(); testFuncN(1.); testFuncS(\"Hello\"); ")); // SquirrelObject main = SquirrelVM::CompileBuffer(_SC("testFunc0(); testFuncN(1); testFuncN(1.23); testFuncS(\"Hello\");")); SquirrelObject main = SquirrelVM::CompileBuffer(_SC("table1 <- {key1=\"keyVal\",key2 = 123};\n if (\"key1\" in table1)\n print(\"Sq: Found it\");\n else\n print(\"Sq: Not found\");")); SquirrelVM::RunScript(main); SquirrelObject table1 = root.GetValue(_SC("table1")); if (table1.Exists(_SC("key1"))) { scprintf(_SC("C++: Found it.\n")); } else { scprintf(_SC("C++: Did not find it.\n")); } // if // === BEGIN Simple variable binding tests === int iVar = 777; float fVar = 88.99f; bool bVar = true; BindVariable(root,&iVar,_SC("iVar")); BindVariable(root,&fVar,_SC("fVar")); BindVariable(root,&bVar,_SC("bVar")); static ScriptStringVar128 testString; scsprintf(testString,_SC("This is a test string")); BindVariable(root,&testString,_SC("testString")); // === END Simple variable binding tests === // === BEGIN Array Tests === SquirrelObject array = SquirrelVM::CreateArray(10); int i; for (i = 0; i < 10; i++) array.SetValue(i,i); array.ArrayAppend(123); // int array.ArrayAppend(true); // bool (must use bool and not SQBool (SQBool is treated as INT by compiler). array.ArrayAppend(false); // bool (must use bool and not SQBool (SQBool is treated as INT by compiler). array.ArrayAppend(123.456f); // float array.ArrayAppend(_SC("string")); // string array.ArrayAppend(456); // Will be popped and thrown away (below). // Pop 3 items from array: array.ArrayPop(SQFalse); // Don't retrieve the popped value (int:123). SquirrelObject so1 = array.ArrayPop(); // Retrieve the popped value. const SQChar * val1 = so1.ToString(); // Get string. float val2 = array.ArrayPop().ToFloat(); // Pop and get float. scprintf(_SC("[Popped values] Val1: %s, Val2: %f\n"),val1,val2); int startIndex = array.Len(); array.ArrayExtend(10); // Implemented as: ArrayResize(Len()+amount). for (i = startIndex; i < array.Len(); i++) array.SetValue(i,i*10); root.SetValue(_SC("array"),array); SquirrelObject arrayr = array.Clone(); // Get a copy as opposed to another reference. arrayr.ArrayReverse(); root.SetValue(_SC("arrayr"),arrayr); // === END Array Tests === // SquirrelObject test = SquirrelVM::CompileBuffer(_SC(" print(iVar); print(fVar); print(bVar); iVar += 1; fVar += 100.; bVar = false; print(iVar); print(fVar); print(bVar); xVar = 1; ")); // Test for xVar error. // SquirrelObject test = SquirrelVM::CompileBuffer(_SC(" print(iVar); print(fVar); print(bVar); iVar += 1; fVar += 100.; bVar = false; print(iVar); print(fVar); print(bVar); print(testString); testString = \"New string value\"; print(testString);")); SquirrelObject define_printArray = SquirrelVM::CompileBuffer(_SC(" function printArray(name,array) { print(name+\".len() = \"+array.len()); foreach(i, v in array) if (v != null) { if (typeof v == \"bool\") v = v ? \"true\" : \"false\"; print(\"[\"+i+\"]: \"+v); } } ")); SquirrelVM::RunScript(define_printArray); SquirrelObject test = SquirrelVM::CompileBuffer(_SC(" printArray(\"array\",array); printArray(\"arrayr\",arrayr); ")); // SquirrelObject test = SquirrelVM::CompileBuffer(_SC(" iVar = 1; print(iVar); ")); // SquirrelObject test = SquirrelVM::CompileBuffer(_SC(" print(\"GB:\"+GB.TEST_CONST); GB.TEST_CONST += 1; GB.Update(); print(\"GB2:\"+GB.TEST_CONST); \n")); SquirrelVM::RunScript(test); #endif } // try catch (SquirrelError & e) { // SquirrelVM::DumpStack(); SQChar buff[256]; scsprintf(buff,_SC("Error: %s, %s\n"),e.desc,_SC("Squirrel::TestObj")); // OutputDebugString(buff); SCPUTS(buff); } // catch } ~TestSqPlus() { SquirrelVM::Shutdown(); } }; void doTest(void) { TestSqPlus testSqPlus; } // doTest int main(int argc,char * argv[]) { // Run twice to make sure cleanup/shutdown works OK. SCPUTS(_SC("Start Pass 1\n")); doTest(); #if 0 SCPUTS(_SC("Start Pass 2\n")); doTest(); #endif SCPUTS(_SC("Done.\n")); scprintf(_SC("Press RETURN to exit.")); getchar(); return 0; }