(svn r12409) [NoAI] -Add: allow an AdvancedMethod which gives you complete control over the param handling from a call from SQ noai
authortruebrain
Tue, 25 Mar 2008 12:09:42 +0000
branchnoai
changeset 9813 9646f7e37c31
parent 9812 4bc3062476c8
child 9814 be51ea0adc29
(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
src/squirrel.hpp
src/squirrel_class.hpp
src/squirrel_helper.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.
--- 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 <typename Func>
+	void DefSQAdvancedMethod(Squirrel *engine, Func function_proc, const char *function_name)
+	{
+		using namespace SQConvert;
+		engine->AddMethod(function_name, DefSQAdvancedNonStaticCallback<CL, Func>, 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
--- 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<Targ1>(), vm, 2)
 			);
-			sq_remove(vm, 2);
+			sq_pop(vm, 1);
 			return Return(vm, ret);
 		}
 	};
@@ -166,7 +166,7 @@
 			(*func)(
 				GetParam(ForceType<Targ1>(), vm, 2)
 			);
-			sq_remove(vm, 2);
+			sq_pop(vm, 1);
 			return 0;
 		}
 	};
@@ -181,7 +181,7 @@
 			Tretval ret = (instance->*func)(
 				GetParam(ForceType<Targ1>(), vm, 2)
 			);
-			sq_remove(vm, 2);
+			sq_pop(vm, 1);
 			return Return(vm, ret);
 		}
 	};
@@ -196,7 +196,7 @@
 			(instance->*func)(
 				GetParam(ForceType<Targ1>(), vm, 2)
 			);
-			sq_remove(vm, 2);
+			sq_pop(vm, 1);
 			return 0;
 		}
 
@@ -221,8 +221,7 @@
 				GetParam(ForceType<Targ1>(), vm, 2),
 				GetParam(ForceType<Targ2>(), vm, 3)
 			);
-			sq_remove(vm, 2);
-			sq_remove(vm, 3);
+			sq_pop(vm, 2);
 			return Return(vm, ret);
 		}
 	};
@@ -238,8 +237,7 @@
 				GetParam(ForceType<Targ1>(), vm, 2),
 				GetParam(ForceType<Targ2>(), vm, 3)
 			);
-			sq_remove(vm, 2);
-			sq_remove(vm, 3);
+			sq_pop(vm, 2);
 			return 0;
 		}
 	};
@@ -255,8 +253,7 @@
 				GetParam(ForceType<Targ1>(), vm, 2),
 				GetParam(ForceType<Targ2>(), vm, 3)
 			);
-			sq_remove(vm, 2);
-			sq_remove(vm, 3);
+			sq_pop(vm, 2);
 			return Return(vm, ret);
 		}
 	};
@@ -272,8 +269,7 @@
 				GetParam(ForceType<Targ1>(), vm, 2),
 				GetParam(ForceType<Targ2>(), vm, 3)
 			);
-			sq_remove(vm, 2);
-			sq_remove(vm, 3);
+			sq_pop(vm, 2);
 			return 0;
 		}
 
@@ -300,9 +296,7 @@
 				GetParam(ForceType<Targ2>(), vm, 3),
 				GetParam(ForceType<Targ3>(), 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<Targ2>(), vm, 3),
 				GetParam(ForceType<Targ3>(), 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<Targ2>(), vm, 3),
 				GetParam(ForceType<Targ3>(), 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<Targ2>(), vm, 3),
 				GetParam(ForceType<Targ3>(), 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<Targ3>(), vm, 4),
 				GetParam(ForceType<Targ4>(), 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<Targ3>(), vm, 4),
 				GetParam(ForceType<Targ4>(), 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<Targ3>(), vm, 4),
 				GetParam(ForceType<Targ4>(), 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<Targ3>(), vm, 4),
 				GetParam(ForceType<Targ4>(), 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<Targ4>(), vm, 5),
 				GetParam(ForceType<Targ5>(), 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<Targ4>(), vm, 5),
 				GetParam(ForceType<Targ5>(), 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<Targ4>(), vm, 5),
 				GetParam(ForceType<Targ5>(), 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<Targ4>(), vm, 5),
 				GetParam(ForceType<Targ5>(), 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<Tmethod>::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 <typename Tcls, typename Tmethod>
+	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.