# HG changeset patch # User truebrain # Date 1206446982 0 # Node ID 9646f7e37c31102e2ac4b8a7bd42a5d448c90af6 # Parent 4bc3062476c870812567d95828e23402fb63be6e (svn r12409) [NoAI] -Add: allow an AdvancedMethod which gives you complete control over the param handling from a call from SQ [NoAI] -Fix: many stack-cleanup fixes; this makes the stack in multiple calls not to overflow diff -r 4bc3062476c8 -r 9646f7e37c31 src/squirrel.hpp --- a/src/squirrel.hpp Sun Mar 23 21:45:16 2008 +0000 +++ b/src/squirrel.hpp Tue Mar 25 12:09:42 2008 +0000 @@ -120,7 +120,7 @@ * @note This will only work just after a function-call from within Squirrel * to your C++ function. */ - static bool GetInstance(HSQUIRRELVM vm, HSQOBJECT *ptr) { sq_getclass(vm, 1); sq_getstackobj(vm, 1, ptr); return true; } + static bool GetInstance(HSQUIRRELVM vm, HSQOBJECT *ptr) { sq_getclass(vm, 1); sq_getstackobj(vm, 1, ptr); sq_pop(vm, 1); return true; } /** * Convert a Squirrel-object to a string. diff -r 4bc3062476c8 -r 9646f7e37c31 src/squirrel_class.hpp --- a/src/squirrel_class.hpp Sun Mar 23 21:45:16 2008 +0000 +++ b/src/squirrel_class.hpp Tue Mar 25 12:09:42 2008 +0000 @@ -39,6 +39,16 @@ } /** + * This defines a method inside a class for Squirrel, which has access to the 'engine' (experts only!). + */ + template + void DefSQAdvancedMethod(Squirrel *engine, Func function_proc, const char *function_name) + { + using namespace SQConvert; + engine->AddMethod(function_name, DefSQAdvancedNonStaticCallback, 0, NULL, &function_proc, sizeof(function_proc)); + } + + /** * This defines a method inside a class for Squirrel with defined the params. * @note If you define nparam, make sure that he first param is always 'x', * which is the 'this' inside the function. This is hidden from the rest diff -r 4bc3062476c8 -r 9646f7e37c31 src/squirrel_helper.hpp --- a/src/squirrel_helper.hpp Sun Mar 23 21:45:16 2008 +0000 +++ b/src/squirrel_helper.hpp Tue Mar 25 12:09:42 2008 +0000 @@ -151,7 +151,7 @@ Tretval ret = (*func)( GetParam(ForceType(), vm, 2) ); - sq_remove(vm, 2); + sq_pop(vm, 1); return Return(vm, ret); } }; @@ -166,7 +166,7 @@ (*func)( GetParam(ForceType(), vm, 2) ); - sq_remove(vm, 2); + sq_pop(vm, 1); return 0; } }; @@ -181,7 +181,7 @@ Tretval ret = (instance->*func)( GetParam(ForceType(), vm, 2) ); - sq_remove(vm, 2); + sq_pop(vm, 1); return Return(vm, ret); } }; @@ -196,7 +196,7 @@ (instance->*func)( GetParam(ForceType(), vm, 2) ); - sq_remove(vm, 2); + sq_pop(vm, 1); return 0; } @@ -221,8 +221,7 @@ GetParam(ForceType(), vm, 2), GetParam(ForceType(), vm, 3) ); - sq_remove(vm, 2); - sq_remove(vm, 3); + sq_pop(vm, 2); return Return(vm, ret); } }; @@ -238,8 +237,7 @@ GetParam(ForceType(), vm, 2), GetParam(ForceType(), vm, 3) ); - sq_remove(vm, 2); - sq_remove(vm, 3); + sq_pop(vm, 2); return 0; } }; @@ -255,8 +253,7 @@ GetParam(ForceType(), vm, 2), GetParam(ForceType(), vm, 3) ); - sq_remove(vm, 2); - sq_remove(vm, 3); + sq_pop(vm, 2); return Return(vm, ret); } }; @@ -272,8 +269,7 @@ GetParam(ForceType(), vm, 2), GetParam(ForceType(), vm, 3) ); - sq_remove(vm, 2); - sq_remove(vm, 3); + sq_pop(vm, 2); return 0; } @@ -300,9 +296,7 @@ GetParam(ForceType(), vm, 3), GetParam(ForceType(), vm, 4) ); - sq_remove(vm, 2); - sq_remove(vm, 3); - sq_remove(vm, 4); + sq_pop(vm, 3); return Return(vm, ret); } }; @@ -319,9 +313,7 @@ GetParam(ForceType(), vm, 3), GetParam(ForceType(), vm, 4) ); - sq_remove(vm, 2); - sq_remove(vm, 3); - sq_remove(vm, 4); + sq_pop(vm, 3); return 0; } }; @@ -338,9 +330,7 @@ GetParam(ForceType(), vm, 3), GetParam(ForceType(), vm, 4) ); - sq_remove(vm, 2); - sq_remove(vm, 3); - sq_remove(vm, 4); + sq_pop(vm, 3); return Return(vm, ret); } }; @@ -357,9 +347,7 @@ GetParam(ForceType(), vm, 3), GetParam(ForceType(), vm, 4) ); - sq_remove(vm, 2); - sq_remove(vm, 3); - sq_remove(vm, 4); + sq_pop(vm, 3); return 0; } @@ -388,10 +376,7 @@ GetParam(ForceType(), vm, 4), GetParam(ForceType(), vm, 5) ); - sq_remove(vm, 2); - sq_remove(vm, 3); - sq_remove(vm, 4); - sq_remove(vm, 5); + sq_pop(vm, 4); return Return(vm, ret); } }; @@ -409,10 +394,7 @@ GetParam(ForceType(), vm, 4), GetParam(ForceType(), vm, 5) ); - sq_remove(vm, 2); - sq_remove(vm, 3); - sq_remove(vm, 4); - sq_remove(vm, 5); + sq_pop(vm, 4); return 0; } }; @@ -430,10 +412,7 @@ GetParam(ForceType(), vm, 4), GetParam(ForceType(), vm, 5) ); - sq_remove(vm, 2); - sq_remove(vm, 3); - sq_remove(vm, 4); - sq_remove(vm, 5); + sq_pop(vm, 4); return Return(vm, ret); } }; @@ -451,10 +430,7 @@ GetParam(ForceType(), vm, 4), GetParam(ForceType(), vm, 5) ); - sq_remove(vm, 2); - sq_remove(vm, 3); - sq_remove(vm, 4); - sq_remove(vm, 5); + sq_pop(vm, 4); return 0; } @@ -485,11 +461,7 @@ GetParam(ForceType(), vm, 5), GetParam(ForceType(), vm, 6) ); - sq_remove(vm, 2); - sq_remove(vm, 3); - sq_remove(vm, 4); - sq_remove(vm, 5); - sq_remove(vm, 6); + sq_pop(vm, 5); return Return(vm, ret); } }; @@ -508,11 +480,7 @@ GetParam(ForceType(), vm, 5), GetParam(ForceType(), vm, 6) ); - sq_remove(vm, 2); - sq_remove(vm, 3); - sq_remove(vm, 4); - sq_remove(vm, 5); - sq_remove(vm, 6); + sq_pop(vm, 5); return 0; } }; @@ -531,11 +499,7 @@ GetParam(ForceType(), vm, 5), GetParam(ForceType(), vm, 6) ); - sq_remove(vm, 2); - sq_remove(vm, 3); - sq_remove(vm, 4); - sq_remove(vm, 5); - sq_remove(vm, 6); + sq_pop(vm, 5); return Return(vm, ret); } }; @@ -554,11 +518,7 @@ GetParam(ForceType(), vm, 5), GetParam(ForceType(), vm, 6) ); - sq_remove(vm, 2); - sq_remove(vm, 3); - sq_remove(vm, 4); - sq_remove(vm, 5); - sq_remove(vm, 6); + sq_pop(vm, 5); return 0; } @@ -600,19 +560,58 @@ sq_get(vm, -2); sq_pushobject(vm, instance); if (sq_instanceof(vm) != SQTrue) return sq_throwerror(vm, _SC("class method is non-static")); - sq_settop(vm, nparam); + sq_pop(vm, 3); /* Get the 'real' instance of this class */ sq_getinstanceup(vm, 1, &real_instance, 0); /* Get the real function pointer */ sq_getuserdata(vm, nparam, &ptr, 0); if (real_instance == NULL) return sq_throwerror(vm, _SC("couldn't detect real instance of class for non-static call")); + /* Remove the userdata from the stack */ + sq_pop(vm, 1); /* Delegate it to a template that can handle this specific function */ return HelperT::SQCall((Tcls *)real_instance, *(Tmethod *)ptr, vm); } /** + * A general template for all non-static advanced method callbacks from Squirrel. + * In here the function_proc is recovered, and the SQCall is called that + * can handle this exact amount of params. + */ + template + inline SQInteger DefSQAdvancedNonStaticCallback(HSQUIRRELVM vm) + { + /* Find the amount of params we got */ + int nparam = sq_gettop(vm); + SQUserPointer ptr = NULL; + SQUserPointer real_instance = NULL; + HSQOBJECT instance; + + /* Get the 'SQ' instance of this class */ + Squirrel::GetInstance(vm, &instance); + + /* Protect against calls to a non-static method in a static way */ + sq_pushroottable(vm); + sq_pushstring(vm, OTTD2FS(Tcls::GetClassName()), -1); + sq_get(vm, -2); + sq_pushobject(vm, instance); + if (sq_instanceof(vm) != SQTrue) return sq_throwerror(vm, _SC("class method is non-static")); + sq_pop(vm, 3); + + /* Get the 'real' instance of this class */ + sq_getinstanceup(vm, 1, &real_instance, 0); + /* Get the real function pointer */ + sq_getuserdata(vm, nparam, &ptr, 0); + if (real_instance == NULL) return sq_throwerror(vm, _SC("couldn't detect real instance of class for non-static call")); + /* Remove the userdata from the stack */ + sq_pop(vm, 1); + + /* Call the function, which its only param is always the VM */ + return (SQInteger)(((Tcls *)real_instance)->*(*(Tmethod *)ptr))(vm); + } + + /** * A general template for all function/static method callbacks from Squirrel. * In here the function_proc is recovered, and the SQCall is called that * can handle this exact amount of params.