acsitdo
The following code produces an error:
#include <stdarg.h> #include <stdio.h> #include <squirrel.h> #include <sqstdio.h> #include <sqstdaux.h> #include <sqplus.h> #ifdef SQUNICODE #define scvprintf vwprintf #else #define scvprintf vprintf #endif class Point3 { public: float x, y, z; }; DECLARE_INSTANCE_TYPE(Point3); class Entity { public: void test(Point3& p) { if (scriptTest.func.IsNull()) printf("invalid function\n"); else { printf("p = {%f, %f, %f}\n", p.x, p.y, p.z); scriptTest(p); } } static int construct(HSQUIRRELVM v) { printf("construct()\n"); StackHandler sa(v); Entity *self = new Entity(); self->scriptTest = SqPlus::SquirrelFunction<void>(sa.GetObjectHandle(1),_T("test")); self->scriptObjHandle = sa.GetObjectHandle(1); sq_addref(SquirrelVM::GetVMPtr(), &self->scriptObjHandle); return SqPlus::PostConstruct<Entity>(v, self, release); } SQ_DECLARE_RELEASE(Entity); private: SqPlus::SquirrelFunction<void> scriptTest; HSQOBJECT scriptObjHandle; }; DECLARE_INSTANCE_TYPE(Entity); void printfunc(HSQUIRRELVM v, const SQChar *s, ...) { va_list arglist; va_start(arglist, s); vprintf(s, arglist); va_end(arglist); } int main() { SquirrelVM::Init(); sq_setprintfunc(SquirrelVM::GetVMPtr(), printfunc); HSQUIRRELVM v = SquirrelVM::GetVMPtr(); SqPlus::SQClassDef<Entity>("Entity") .staticFuncVarArgs(&Entity::construct, "constructor", "*") ; SqPlus::SQClassDef<Point3>("Point3") ; SquirrelObject inst = SquirrelVM::CompileBuffer("\ class A extends Entity {\n\ function test(pos) {value=1; print(\"pos.x = \"+pos.x);}\n\ value = 10;\n\ };\n\ function create() {return A();}\n\ "); SquirrelVM::RunScript(inst); Entity *e = SqPlus::SquirrelFunction<Entity*>("create")(); Point3 pt = {1,2,3}; e->test(pt); SquirrelVM::Shutdown(); return 0; }
When executed it produces the following output:
construct() p = {1.000000, 2.000000, 3.000000} AN ERROR HAS OCCURED [the index 'value' does not exist] CALLSTACK *FUNCTION [test()] console buffer line [2] LOCALS [pos] INSTANCE [this] TABLE
Note that error is in referencing member value and type of this is table.
That is because of bug in CreateConstructNativeClassInstance function.
inline BOOL CreateConstructNativeClassInstance(HSQUIRRELVM v,const SQChar * className) { int oldtop = sq_gettop(v); sq_pushroottable(v); sq_pushstring(v,className,-1); if (SQ_FAILED(sq_rawget(v,-2))) { // Get the class (created with sq_newclass()). sq_settop(v,oldtop); return FALSE; } // if sq_remove(v,-3); // Remove the root table. sq_push(v,1); // Push the 'this'. if (SQ_FAILED(sq_call(v,1,SQTrue))) { // Call ClassName(): creates new instance and calls constructor (instead of sq_createinstance() where constructor is not called). sq_settop(v,oldtop); return FALSE; } // if sq_remove(v,-2); // Remove the class. // int newtop = sq_gettop(v); return TRUE; } // CreateConstructNativeClassInstance
Bug is in these lines:
sq_remove(v,-3); // Remove the root table. //^ -3 is index before root table pushed first at beginning of this function! sq_push(v,1); // Push the 'this'. //^ 1 is also invalid index because there was something on stack before
To fix this it is needed to replace them with
sq_remove(v,-2); // Remove the root table. sq_pushroottable(v); // Push the 'this'.