1 // SqPlus.h
2 // Created by John Schultz 9/05/05, major update 10/05/05.
3 // Template function call design from LuaPlusCD by Joshua C. Jensen,
4 // inspired by luabind which was inspired by boost::python.
5 // Const argument, const member functions, and Mac OS-X changes by Simon Michelmore.
6 // DECLARE_INSTANCE_TYPE_NAME changes by Ben (Project5) from http://www.squirrel-lang.org/forums/.
7 // Added Kamaitati's changes 5/28/06.
8 // Free for any use.
9 
10 #ifndef _SQ_PLUS_H_
11 #define _SQ_PLUS_H_
12 
13 #include <stdlib.h>
14 #include <string.h>
15 
16 #ifdef __APPLE__
17   #include <malloc/malloc.h>
18 #else
19   // C::B patch: support for FreeBSD
20   #ifdef __FreeBSD__
21     #include <stdlib.h>
22   #else
23     #include <malloc.h>
24   #endif
25 #endif
26 #include <memory.h>
27 #if defined(_MSC_VER) || defined(__BORLANDC__)
28   #include <tchar.h>
29   #ifndef UNICODE
30     #define SCSNPRINTF _snprintf
31     #define SCPUTS puts
32   #else
33     #define SCSNPRINTF _snwprintf
34     #define SCPUTS _putws
35   #endif
36 #else
37   // C::B patch: Convert conflicting _T() to sqT() --> applies to nearly *all* files!
38 //  #define _T(n) n
39   #define sqT(n) n
40   #define SCSNPRINTF snprintf
41   #include <stdio.h> // for snprintf
42   #define SCPUTS puts
43 #endif
44 
45 #if 1
46 #define SQ_CALL_RAISE_ERROR SQTrue
47 #else
48 #define SQ_CALL_RAISE_ERROR SQFalse
49 #endif
50 
51 // this does the same as commenting out the "#ifdef _UNICODE"-stuff in our
52 // bundled squirrel.h, but works also for system-squirrel
53 #ifdef _UNICODE
54   #undef _UNICODE
55   #include "squirrel.h"
56   #define _UNICODE
57 #else
58   #include "squirrel.h"
59 #endif // _UNICODE
60 // C::B patch: so it builds on 64bit, ecapsulate bool/int/float using Squirrel types (this patch applies everywhere, where threse types are used)
61 typedef SQInteger BOOL_T;
62 typedef SQInteger INT_T;
63 typedef SQFloat   FLOAT_T;
64 #define TRUE 1
65 #define FALSE 0
66 
67 #include "SquirrelObject.h"
68 #include "SquirrelVM.h"
69 #include "SquirrelBindingsUtils.h"
70 
71 namespace SqPlus {
72 
73 // === Class Inheritance Support ===
74 // Inheritance in Squirrel allows one class to inherit a base class's functions and variables.
75 // Variables are merged: if Derived has a var name 'val' and Base has a var of the same name,
76 // the resulting var 'val' will take Derived's initialization value.
77 // Functions are not merged, and can be called via Squirrel scoping rules.
78 
79 // Define SQ_USE_CLASS_INHERITANCE to enable class inheritance support
80 // (requires slightly more memory and adds some CPU overhead).
81 // Can also be useful for debugging, as class type information is checked before
82 // dispatching instance function calls and before accessing instance member variables.
83 #define SQ_USE_CLASS_INHERITANCE
84 
85 // Comment out to turn off instance type info support (to save a small amount of memory).
86 #define SQ_SUPPORT_INSTANCE_TYPE_INFO
87 
88 // === Constant argument and constant member function support ===
89 // Define SQPLUS_CONST_OPT before including SqPlus.h for constant argument + constant member function support.
90 // C::B patch: Enable this option
91 #define SQPLUS_CONST_OPT
92 
93 // === Uncomment to support std::string ===
94 //#define SQPLUS_SUPPORT_STD_STRING
95 
96 // === Uncomment to support typedef std::basic_string<SQChar> sq_std_string ===
97 //#define SQPLUS_SUPPORT_SQ_STD_STRING
98 
99 // === Uncomment to support NULL INSTANCE arguments ===
100 //#define SQPLUS_SUPPORT_NULL_INSTANCES
101 
102 // === Uncomment to support C++ style inheritance
103 #define CPP_STYLE_INHERITANCE
104 
105 // === Uncomment to skip sq_argassert() ===
106 //#define SQ_SKIP_ARG_ASSERT
107 
108 template<class T> struct TypeWrapper {};
109 struct SquirrelNull {};
110 struct SQAnything { void * anything; }; // Needed for binding pointers to variables (cannot dereference void *).
111 typedef SQAnything * SQAnythingPtr;
112 typedef SQChar * SQCharPtr;
113 
114 // === Do not use directly: use one of the predefined sizes below ===
115 
116 struct ScriptStringVarBase {
117   //const unsigned char MaxLength; // Real length is MaxLength+1.
118   const SQInteger MaxLength; // C::B patch- to eliminate compiler warning
119   SQChar s[1];
ScriptStringVarBaseScriptStringVarBase120   ScriptStringVarBase(SQInteger _MaxLength) : MaxLength(_MaxLength) {}
121   operator SQChar * () { return &s[0]; }
122   operator void * () { return (void *)&s[0]; }
123   const SQChar * operator = (const SQChar * _s) {
124     return safeStringCopy(s,_s,MaxLength);
125   }
126   // Special safe string copy where MaxLength is 1 less than true buffer length.
127   // strncpy() pads out nulls for the full length of the buffer specified by MaxLength.
safeStringCopyScriptStringVarBase128   static inline SQChar * safeStringCopy(SQChar * d,const SQChar * s,SQInteger MaxLength) {
129     SQInteger i=0;
130     while (s[i]) {
131       d[i] = s[i];
132       i++;
133       if (i == MaxLength) break;
134     } // while
135     d[i] = 0; // Null terminate.
136     return d;
137   } // safeStringCopy
138 };
139 
140 // === Do not use directly: use one of the predefined sizes below ===
141 
142 template<SQInteger MAXLENGTH> // MAXLENGTH is max printable characters (trailing NULL is accounted for in ScriptStringVarBase::s[1]).
143 struct ScriptStringVar : ScriptStringVarBase {
144   SQChar ps[MAXLENGTH];
ScriptStringVarScriptStringVar145   ScriptStringVar() : ScriptStringVarBase(MAXLENGTH) {
146     s[0] = 0;
147   }
ScriptStringVarScriptStringVar148   ScriptStringVar(const SQChar * _s) : ScriptStringVarBase(MAXLENGTH) {
149     *this = _s;
150   }
151   const SQChar * operator = (const SQChar * _s) {
152     return safeStringCopy(s,_s,MaxLength);
153   }
154   const SQChar * operator = (const ScriptStringVar & _s) {
155     return safeStringCopy(s,_s.s,MaxLength);
156   }
157   bool operator == (const ScriptStringVar & _s) {
158     return strcmp(s,_s.s) == 0;
159   }
compareCaseInsensitiveScriptStringVar160   bool compareCaseInsensitive(const ScriptStringVar & _s) {
161     return strcasecmp(s,_s.s) == 0;
162   }
163 };
164 
165 // === Fixed size strings for scripting ===
166 
167 typedef ScriptStringVar<8>   ScriptStringVar8;
168 typedef ScriptStringVar<16>  ScriptStringVar16;
169 typedef ScriptStringVar<32>  ScriptStringVar32;
170 typedef ScriptStringVar<64>  ScriptStringVar64;
171 typedef ScriptStringVar<128> ScriptStringVar128;
172 typedef ScriptStringVar<256> ScriptStringVar256;
173 
174 // === Script Variable Types ===
175 
176 enum ScriptVarType {VAR_TYPE_NONE=-1,VAR_TYPE_INT=0,VAR_TYPE_FLOAT,VAR_TYPE_BOOL,VAR_TYPE_CONST_STRING,VAR_TYPE_STRING,VAR_TYPE_USER_POINTER,VAR_TYPE_INSTANCE};
177 
178 template <typename T>
179 struct TypeInfo {
180   const SQChar * typeName;
181   enum {TypeID=VAR_TYPE_NONE,Size=0};
182 };
183 
184 // === Common Variable Types ===
185 
186 template<>
187 struct TypeInfo<INT_T> {
188   const SQChar * typeName;
189   TypeInfo() : typeName(sqT("int")) {}
190   enum {TypeID=VAR_TYPE_INT,Size=sizeof(INT_T)};
191   operator ScriptVarType() { return ScriptVarType(TypeID); }
192 };
193 
194 template<>
195 struct TypeInfo<FLOAT_T> {
196   const SQChar * typeName;
197   TypeInfo() : typeName(sqT("float")) {}
198   enum {TypeID=VAR_TYPE_FLOAT,Size=sizeof(FLOAT_T)};
199   operator ScriptVarType() { return ScriptVarType(TypeID); }
200 };
201 
202 template<>
203 struct TypeInfo<bool> {
204   const SQChar * typeName;
205   TypeInfo() : typeName(sqT("bool")) {}
206   enum {TypeID=VAR_TYPE_BOOL,Size=sizeof(BOOL_T)};
207   operator ScriptVarType() { return ScriptVarType(TypeID); }
208 };
209 
210 template<>
211 struct TypeInfo<SQUserPointer> {
212   const SQChar * typeName;
213   TypeInfo() : typeName(sqT("SQUserPointer")) {}
214   enum {TypeID=VAR_TYPE_USER_POINTER,Size=sizeof(SQUserPointer)};
215   operator ScriptVarType() { return ScriptVarType(TypeID); }
216 };
217 
218 template<>
219 struct TypeInfo<SQAnything> {
220   const SQChar * typeName;
221   TypeInfo() : typeName(sqT("SQUserPointer")) {}
222   enum {TypeID=VAR_TYPE_USER_POINTER,Size=sizeof(SQUserPointer)};
223   operator ScriptVarType() { return ScriptVarType(TypeID); }
224 };
225 
226 template<>
227 struct TypeInfo<const SQChar *> {
228   const SQChar * typeName;
229   TypeInfo() : typeName(sqT("const SQChar *")) {}
230   enum {TypeID=VAR_TYPE_CONST_STRING,Size=sizeof(const SQChar *)};
231   operator ScriptVarType() { return ScriptVarType(TypeID); }
232 };
233 
234 template<>
235 struct TypeInfo<ScriptStringVarBase> {
236   const SQChar * typeName;
237   TypeInfo() : typeName(sqT("ScriptStringVarBase")) {}
238   enum {TypeID=VAR_TYPE_STRING,Size=sizeof(ScriptStringVarBase)};
239   operator ScriptVarType() { return ScriptVarType(TypeID); }
240 };
241 
242 // === Fixed String Variants ===
243 
244 template<>
245 struct TypeInfo<ScriptStringVar8> {
246   const SQChar * typeName;
247   TypeInfo() : typeName(sqT("ScriptStringVar8")) {}
248   enum {TypeID=VAR_TYPE_STRING,Size=sizeof(ScriptStringVar8)};
249   operator ScriptVarType() { return ScriptVarType(TypeID); }
250 };
251 
252 template<>
253 struct TypeInfo<ScriptStringVar16> {
254   const SQChar * typeName;
255   TypeInfo() : typeName(sqT("ScriptStringVar16")) {}
256   enum {TypeID=VAR_TYPE_STRING,Size=sizeof(ScriptStringVar16)};
257   operator ScriptVarType() { return ScriptVarType(TypeID); }
258 };
259 
260 template<>
261 struct TypeInfo<ScriptStringVar32> {
262   const SQChar * typeName;
263   TypeInfo() : typeName(sqT("ScriptStringVar32")) {}
264   enum {TypeID=VAR_TYPE_STRING,Size=sizeof(ScriptStringVar32)};
265   operator ScriptVarType() { return ScriptVarType(TypeID); }
266 };
267 
268 template<>
269 struct TypeInfo<ScriptStringVar64> {
270   const SQChar * typeName;
271   TypeInfo() : typeName(sqT("ScriptStringVar64")) {}
272   enum {TypeID=VAR_TYPE_STRING,Size=sizeof(ScriptStringVar64)};
273   operator ScriptVarType() { return ScriptVarType(TypeID); }
274 };
275 
276 template<>
277 struct TypeInfo<ScriptStringVar128> {
278   const SQChar * typeName;
279   TypeInfo() : typeName(sqT("ScriptStringVar128")) {}
280   enum {TypeID=VAR_TYPE_STRING,Size=sizeof(ScriptStringVar128)};
281   operator ScriptVarType() { return ScriptVarType(TypeID); }
282 };
283 
284 template<>
285 struct TypeInfo<ScriptStringVar256> {
286   const SQChar * typeName;
287   TypeInfo() : typeName(sqT("ScriptStringVar256")) {}
288   enum {TypeID=VAR_TYPE_STRING,Size=sizeof(ScriptStringVar256)};
289   operator ScriptVarType() { return ScriptVarType(TypeID); }
290 };
291 
292 enum VarAccessType {VAR_ACCESS_READ_WRITE=0,VAR_ACCESS_READ_ONLY=1<<0,VAR_ACCESS_CONSTANT=1<<1,VAR_ACCESS_STATIC=1<<2};
293 
294 // See VarRef and ClassType<> below: for instance assignment.
295 typedef void (*CopyVarFunc)(void * dst,void * src);
296 
297 // === Variable references for script access ===
298 
299 #define SQ_PLUS_TYPE_TABLE sqT("__SqTypes")
300 
301 struct VarRef {
302   // In this case 'offsetOrAddrOrConst' is simpler than using an anonymous union.
303   void * offsetOrAddrOrConst; // Instance member variable offset from 'this' pointer base (as size_t), or address if static variable (void *), or constant value.
304   ScriptVarType type;         // Variable type (from enum above).
305   SQUserPointer instanceType; // Unique ID for the containing class instance (for instance vars only). When the var is an instance, its type is encoded in copyFunc.
306   CopyVarFunc copyFunc;       // Function pointer to copy variables (for instance variables only).
307   //short size;                 // Currently for debugging only (size of item when pointer to item is dereferenced). Could be used for variable max string buffer length.
308   SQInteger size;                 // Currently for debugging only (size of item when pointer to item is dereferenced). Could be used for variable max string buffer length.
309   short access;               // VarAccessType.
310   const SQChar * typeName;    // Type name string (to create instances by name).
311   VarRef() : offsetOrAddrOrConst(0), type(VAR_TYPE_NONE), instanceType((SQUserPointer)-1), copyFunc(0), size(0), access(VAR_ACCESS_READ_WRITE) {}
312   VarRef(void * _offsetOrAddrOrConst, ScriptVarType _type, SQUserPointer _instanceType, CopyVarFunc _copyFunc, SQInteger _size,VarAccessType _access,const SQChar * _typeName) :
313          offsetOrAddrOrConst(_offsetOrAddrOrConst), type(_type), instanceType(_instanceType), copyFunc(_copyFunc), size(_size), access(_access), typeName(_typeName) {
314 #ifdef SQ_SUPPORT_INSTANCE_TYPE_INFO
315     SquirrelObject typeTable = SquirrelVM::GetRootTable().GetValue(SQ_PLUS_TYPE_TABLE);
316     if (typeTable.IsNull()) {
317       typeTable = SquirrelVM::CreateTable();
318       SquirrelObject root = SquirrelVM::GetRootTable();
319       root.SetValue(SQ_PLUS_TYPE_TABLE,typeTable);
320     } // if
321     typeTable.SetValue(INT_T((size_t)copyFunc),typeName);
322 #endif
323   }
324 };
325 
326 typedef VarRef * VarRefPtr;
327 
328 // Internal use only.
329 inline void getVarNameTag(SQChar * buff,INT_T maxSize,const SQChar * scriptName) {
330 //  assert(maxSize > 3);
331 #if 1
332   SQChar * d = buff;
333   d[0] = '_';
334   d[1] = 'v';
335   d = &d[2];
336   maxSize -= (2+1); // +1 = space for null.
337   SQInteger pos=0;
338   while (scriptName[pos] && pos < maxSize) {
339     d[pos] = scriptName[pos];
340     pos++;
341   } // while
342   d[pos] = 0; // null terminate.
343 #else
344   SCSNPRINTF(buff,maxSize,sqT("_v%s"),scriptName);
345 #endif
346 } // getVarNameTag
347 
348 // Internal use only.
349 SQInteger setVarFunc(HSQUIRRELVM v);
350 SQInteger getVarFunc(HSQUIRRELVM v);
351 SQInteger setInstanceVarFunc(HSQUIRRELVM v);
352 SQInteger getInstanceVarFunc(HSQUIRRELVM v);
353 
354 // === BEGIN Helpers ===
355 
356 inline void createTableSetGetHandlers(SquirrelObject & so) {
357   SquirrelObject delegate = so.GetDelegate();
358   if (!delegate.Exists(sqT("_set"))) {
359     delegate = SquirrelVM::CreateTable();
360     SquirrelVM::CreateFunction(delegate,setVarFunc,sqT("_set"),sqT("sn|b|s")); // String var name = number(SQInteger or float) or bool or string.
361     SquirrelVM::CreateFunction(delegate,getVarFunc,sqT("_get"),sqT("s"));      // String var name.
362     so.SetDelegate(delegate);
363   } // if
364 } // createTableSetGetHandlers
365 
366 inline VarRefPtr createVarRef(SquirrelObject & so,const SQChar * scriptVarName) {
367   VarRefPtr pvr=0;
368   ScriptStringVar256 scriptVarTagName; getVarNameTag(scriptVarTagName,sizeof(scriptVarTagName),scriptVarName);
369   if (!so.GetUserData(scriptVarTagName,(SQUserPointer *)&pvr)) {
370     so.NewUserData(scriptVarTagName,sizeof(*pvr));
371     if (!so.GetUserData(scriptVarTagName,(SQUserPointer *)&pvr)) throw SquirrelError(sqT("Could not create UserData."));
372   } // if
373   return pvr;
374 } // createVarRef
375 
376 template<typename T>
377 void validateConstantType(T /*constant*/) {
378   switch(TypeInfo<T>()) {
379   case VAR_TYPE_INT:
380   case VAR_TYPE_FLOAT:
381   case VAR_TYPE_BOOL:
382   case VAR_TYPE_CONST_STRING:
383     break;
384   default:
385     throw SquirrelError(sqT("validateConstantType(): type must be INT, FLOAT, BOOL, or CONST CHAR *."));
386   } // case
387 } // validateConstantType
388 
389 inline void createInstanceSetGetHandlers(SquirrelObject & so) {
390   if (!so.Exists(sqT("_set"))) {
391     SquirrelVM::CreateFunction(so,setInstanceVarFunc,sqT("_set"),sqT("sn|b|s|x")); // String var name = number(SQInteger or float) or bool or string or instance.
392     SquirrelVM::CreateFunction(so,getInstanceVarFunc,sqT("_get"),sqT("s"));      // String var name.
393   } // if
394 } // createInstanceSetGetHandlers
395 
396 // === END Helpers ===
397 
398 // === Class Type Helper class: returns a unique number for each class type ===
399 
400 template<typename T>
401 struct ClassType {
402   static SQUserPointer type(void) { return (SQUserPointer)&copy; }
403   static CopyVarFunc getCopyFunc(void) { return (CopyVarFunc)&copy; }
404   static void copy(T * dst,T * src) {
405     *dst = *src;
406   } // copy
407 };
408 
409 // === Bind a global or pre-allocated (not instance) class member variable or constant (for tables only (not classes)) ===
410 
411 template<typename T>
412 void BindVariable(SquirrelObject & so,T * var,const SQChar * scriptVarName,VarAccessType access=VAR_ACCESS_READ_WRITE) {
413   VarRefPtr pvr = createVarRef(so,scriptVarName);
414   *pvr = VarRef(var,TypeInfo<T>(),0,ClassType<T>::getCopyFunc(),sizeof(*var),access,TypeInfo<T>().typeName);
415   createTableSetGetHandlers(so);
416 } // BindVariable
417 
418 // === Bind a constant by value: INT_T, FLOAT_T, BOOL_T, or CONST CHAR * (for tables only (not classes)) ===
419 
420 template<typename T>
421 void BindConstant(SquirrelObject & so,T constant,const SQChar * scriptVarName) {
422   validateConstantType(constant);
423   VarRefPtr pvr = createVarRef(so,scriptVarName);
424   // C::B patch: Handler for newer compilers
425 #if __cplusplus>=201103L
426   static_assert(sizeof(constant)<=sizeof(void*), "using larger type");
427 #endif
428   void *ptr = reinterpret_cast<void*>(constant);
429   *pvr = VarRef(ptr,TypeInfo<T>(),0,0,sizeof(constant),VAR_ACCESS_CONSTANT,TypeInfo<T>().typeName);
430   createTableSetGetHandlers(so);
431 } // BindConstant
432 
433 template<typename T>
434 void BindVariable(T * var,const SQChar * scriptVarName,VarAccessType access=VAR_ACCESS_READ_WRITE) {
435   SquirrelObject so = SquirrelVM::GetRootTable();
436   BindVariable(so,var,scriptVarName,access);
437 } // BindVariable
438 
439 template<typename T>
440 void BindConstant(T constant,const SQChar * scriptVarName) {
441   SquirrelObject so = SquirrelVM::GetRootTable();
442   BindConstant(so,constant,scriptVarName);
443 } // BindConstant
444 
445 // === Register a class instance member variable or constant. var argument provides type and offset ( effectively &((ClassType *)0)->var ) ===
446 
447 // classType is the type of the member variable's containing class.
448 template<typename T>
449 void RegisterInstanceVariable(SquirrelObject & so,SQUserPointer classType,T * var,const SQChar * scriptVarName,VarAccessType access=VAR_ACCESS_READ_WRITE) {
450   VarRef * pvr = createVarRef(so,scriptVarName);
451   void * offsetOrAddrOrConst = (void *)var; // var must be passed in as &obj->var, where obj = 0 (the address is the offset), or as static/global address.
452   *pvr = VarRef(offsetOrAddrOrConst,TypeInfo<T>(),classType,ClassType<T>::getCopyFunc(),sizeof(*var),access,TypeInfo<T>().typeName);
453   createInstanceSetGetHandlers(so);
454 } // RegisterInstanceVariable
455 
456 template<typename T>
457 void RegisterInstanceConstant(SquirrelObject & so,SQUserPointer classType,T constant,const SQChar * scriptVarName) {
458   validateConstantType(constant);
459   VarRef * pvr = createVarRef(so,scriptVarName);
460   struct CV {
461     T var;
462     size_t pad;
463   } cv; // Cast Variable helper.
464   cv.var = constant;
465   *pvr = VarRef(*(void **)&cv,TypeInfo<T>(),classType,0,sizeof(constant),VAR_ACCESS_CONSTANT,TypeInfo<T>().typeName);
466   createInstanceSetGetHandlers(so);
467 } // RegisterInstanceConstant
468 
469 //////////////////////////////////////////////////////////////////////////
470 /////////// BEGIN Generalized Class/Struct Instance Support //////////////
471 //////////////////////////////////////////////////////////////////////////
472 
473 //BOOL_T CreateNativeClassInstance(HSQUIRRELVM v,const SQChar * classname,SQUserPointer ud,SQRELEASEHOOK hook); // In SquirrelBindingUtils.cpp.
474 
475 // Create native class instance and leave on stack.
476 inline BOOL_T CreateConstructNativeClassInstance(HSQUIRRELVM v,const SQChar * className) {
477   SQInteger oldtop = sq_gettop(v);
478   sq_pushroottable(v);
479   sq_pushstring(v,className,-1);
480   if (SQ_FAILED(sq_rawget(v,-2))) { // Get the class (created with sq_newclass()).
481     sq_settop(v,oldtop);
482     return FALSE;
483   } // if
484 #if 0
485   sq_remove(v,-3); // Remove the root table.
486   sq_push(v,1);    // Push the 'this'.
487 #else // Kamaitati's change. 5/28/06 jcs.
488   sq_remove(v,-2); // Remove the root table.
489   sq_pushroottable(v); // Push the 'this'.
490 #endif
491   if (SQ_FAILED(sq_call(v,1,SQTrue,SQ_CALL_RAISE_ERROR))) { // Call ClassName(): creates new instance and calls constructor (instead of sq_createinstance() where constructor is not called).
492     sq_settop(v,oldtop);
493     return FALSE;
494   } // if
495   sq_remove(v,-2); // Remove the class.
496   //  SQInteger newtop = sq_gettop(v);
497   return TRUE;
498 } // CreateConstructNativeClassInstance
499 
500 // Create new instance, copy 'classToCopy', and store result on stack.
501 template<typename T>
502 inline BOOL_T CreateCopyInstance(const SQChar * className,const T & classToCopy) {
503   HSQUIRRELVM v = SquirrelVM::GetVMPtr();
504   if (!CreateConstructNativeClassInstance(v,className)) {
505     return FALSE;
506   } // if
507   SQUserPointer up=0;
508   sq_getinstanceup(v,-1,&up,ClassType<T>::type());
509   if (!up) return FALSE;
510   T * newClass = (T *)up;
511   *newClass = classToCopy; // <TODO> Optimized version that uses the copy constructor.
512   return TRUE;
513 } // CreateCopyInstance
514 
515 // Create a new copy of type 'className' and copy 'classToCopy', return result via SquirrelObject.
516 template<typename T>
517 inline SquirrelObject NewClassCopy(const SQChar * className,const T & classToCopy) {
518   SquirrelObject ret;
519   if (CreateCopyInstance(className,classToCopy)) {
520     ret.AttachToStackObject(-1);
521     sq_poptop(SquirrelVM::GetVMPtr());
522   } else {
523     throw SquirrelError(sqT("NewClassCopy(): could not create class"));
524   } // if
525   return ret;
526 } // NewClassCopy
527 
528 // Return a new class copy on the stack from a varArgs function call.
529 template<typename T>
530 inline SQInteger ReturnCopy(HSQUIRRELVM v,const T & classToCopy) {
531   SquirrelObject so(NewClassCopy(GetTypeName(classToCopy),classToCopy));
532   return StackHandler(v).Return(so);
533 } // ReturnCopy
534 
535 // Katsuaki Kawachi's GetInstance<> exception change. 6/27/06 jcs
536 
537 // Get an instance of type T from the stack at idx (for function calls).
538 template<typename T,bool ExceptionOnError>
539 T * GetInstance(HSQUIRRELVM v,SQInteger idx) {
540   SQUserPointer up=0;
541   sq_getinstanceup(v,idx,&up,ClassType<T>::type());
542   if (ExceptionOnError) { // This code block should be compiled out when ExceptionOnError is false. In any case, the compiler should not generate a test condition (include or exclude the enclosed code block).
543     if (!up) throw SquirrelError(sqT("GetInstance: Invalid argument type"));
544   } // if
545   return (T *)up;
546 } // GetInstance
547 
548 // NAME and macro changes from Ben's (Project5) forum post. 2/26/06 jcs
549 // Kamaitati's NULL_INSTANCE support. 5/28/06 jcs
550 
551 #ifdef SQPLUS_SUPPORT_NULL_INSTANCES
552 
553 #define DECLARE_INSTANCE_TYPE_NAME_(TYPE,NAME) namespace SqPlus { \
554   inline const SQChar * GetTypeName(const TYPE & /*n*/) { return sqT(#NAME); } \
555   inline void Push(HSQUIRRELVM v,TYPE * value) { \
556     if (!value)  sq_pushnull(v); \
557     else if (!CreateNativeClassInstance(v,GetTypeName(*value),value,0)) \
558       throw SquirrelError(sqT("Push(): could not create INSTANCE (check registration name)")); } \
559   inline void Push(HSQUIRRELVM /*v*/,TYPE & value) { if (!CreateCopyInstance(GetTypeName(value),value)) throw SquirrelError(sqT("Push(): could not create INSTANCE copy (check registration name)")); } \
560   inline bool Match(TypeWrapper<TYPE &>,HSQUIRRELVM v,SQInteger idx) { return  GetInstance<TYPE,false>(v,idx) != NULL; } \
561   inline bool Match(TypeWrapper<TYPE *>,HSQUIRRELVM v,SQInteger idx) { \
562     return (sq_gettype(v,idx)==OT_NULL) || (GetInstance<TYPE,false>(v,idx) != NULL); } \
563   inline TYPE & Get(TypeWrapper<TYPE &>,HSQUIRRELVM v,SQInteger idx) { return *GetInstance<TYPE,true>(v,idx); } \
564   inline TYPE * Get(TypeWrapper<TYPE *>,HSQUIRRELVM v,SQInteger idx) { \
565     if (sq_gettype(v,idx)==OT_NULL) return NULL; \
566     return GetInstance<TYPE,true>(v,idx); } \
567   template<> \
568   struct TypeInfo<TYPE> { \
569     const SQChar * typeName; \
570     TypeInfo() : typeName(sqT(#NAME)) {} \
571     enum {TypeID=VAR_TYPE_INSTANCE,Size=sizeof(TYPE)}; \
572     operator ScriptVarType() { return ScriptVarType(TypeID); } \
573   }; \
574 } // nameSpace SqPlus
575 
576 #else
577 
578 #define DECLARE_INSTANCE_TYPE_NAME_(TYPE,NAME) namespace SqPlus { \
579   inline const SQChar * GetTypeName(const TYPE & /*n*/)            { return sqT(#NAME); } \
580   inline void Push(HSQUIRRELVM v,TYPE * value)                 { if (!CreateNativeClassInstance(v,GetTypeName(*value),value,0)) throw SquirrelError(sqT("Push(): could not create INSTANCE (check registration name)")); } \
581   inline void Push(HSQUIRRELVM /*v*/,TYPE & value)                 { if (!CreateCopyInstance(GetTypeName(value),value)) throw SquirrelError(sqT("Push(): could not create INSTANCE copy (check registration name)")); } \
582   inline bool	Match(TypeWrapper<TYPE &>,HSQUIRRELVM v,SQInteger idx) { return  GetInstance<TYPE,false>(v,idx) != NULL; } \
583   inline bool	Match(TypeWrapper<TYPE *>,HSQUIRRELVM v,SQInteger idx) { return  GetInstance<TYPE,false>(v,idx) != NULL; } \
584   inline TYPE & Get(TypeWrapper<TYPE &>,HSQUIRRELVM v,SQInteger idx) { return *GetInstance<TYPE,true>(v,idx); } \
585   inline TYPE * Get(TypeWrapper<TYPE *>,HSQUIRRELVM v,SQInteger idx) { return  GetInstance<TYPE,true>(v,idx); } \
586   template<> \
587   struct TypeInfo<TYPE> { \
588     const SQChar * typeName; \
589     TypeInfo() : typeName(sqT(#NAME)) {} \
590     enum {TypeID=VAR_TYPE_INSTANCE,Size=sizeof(TYPE)}; \
591     operator ScriptVarType() { return ScriptVarType(TypeID); } \
592   }; \
593 } // nameSpace SqPlus
594 
595 #endif
596 
597 // TYPE or NAME below must match the string name used in SqClassDef<>, otherwise name lookup won't match and Squirrel will throw a "can't create instance" error.
598 #ifndef SQPLUS_CONST_OPT
599 #define DECLARE_INSTANCE_TYPE(TYPE) DECLARE_INSTANCE_TYPE_NAME_(TYPE,TYPE)
600 #define DECLARE_INSTANCE_TYPE_NAME(TYPE,NAME) DECLARE_INSTANCE_TYPE_NAME_(TYPE,NAME)
601 #else
602 #define SQPLUS_DECLARE_INSTANCE_TYPE_CONST
603 #include "SqPlusConst.h"
604 #endif
605 
606 //////////////////////////////////////////////////////////////////////////
607 //////////// END Generalized Class/Struct Instance Support ///////////////
608 //////////////////////////////////////////////////////////////////////////
609 
610 #ifndef SQ_SKIP_ARG_ASSERT
611   #define sq_argassert(arg,_index_) if (!Match(TypeWrapper<P##arg>(),v,_index_)) return sq_throwerror(v,sqT("Incorrect function argument"))
612 #else
613   #define sq_argassert(arg,_index_)
614 #endif
615 
616 // === Return value variants ===
617 
618 template<class RT>
619 struct ReturnSpecialization {
620 
621   // === Standard Function calls ===
622 
623   static SQInteger Call(RT (*func)(),HSQUIRRELVM v,SQInteger /*index*/) {
624     RT ret = func();
625     Push(v,ret);
626     return 1;
627   }
628 
629   template<typename P1>
630   static SQInteger Call(RT (*func)(P1),HSQUIRRELVM v,SQInteger index) {
631     sq_argassert(1,index + 0);
632     RT ret = func(
633       Get(TypeWrapper<P1>(),v,index + 0)
634     );
635     Push(v,ret);
636     return 1;
637   }
638 
639   template<typename P1,typename P2>
640   static SQInteger Call(RT (*func)(P1,P2),HSQUIRRELVM v,SQInteger index) {
641     sq_argassert(1,index + 0);
642     sq_argassert(2,index + 1);
643     RT ret = func(
644       Get(TypeWrapper<P1>(),v,index + 0),
645       Get(TypeWrapper<P2>(),v,index + 1)
646     );
647     Push(v,ret);
648     return 1;
649   }
650 
651   template<typename P1,typename P2,typename P3>
652   static SQInteger Call(RT (*func)(P1,P2,P3),HSQUIRRELVM v,SQInteger index) {
653     sq_argassert(1,index + 0);
654     sq_argassert(2,index + 1);
655     sq_argassert(3,index + 2);
656     RT ret = func(
657       Get(TypeWrapper<P1>(),v,index + 0),
658       Get(TypeWrapper<P2>(),v,index + 1),
659       Get(TypeWrapper<P3>(),v,index + 2)
660     );
661     Push(v,ret);
662     return 1;
663   }
664 
665   template<typename P1,typename P2,typename P3,typename P4>
666   static SQInteger Call(RT (*func)(P1,P2,P3,P4),HSQUIRRELVM v,SQInteger index) {
667     sq_argassert(1,index + 0);
668     sq_argassert(2,index + 1);
669     sq_argassert(3,index + 2);
670     sq_argassert(4,index + 3);
671     RT ret = func(
672       Get(TypeWrapper<P1>(),v,index + 0),
673       Get(TypeWrapper<P2>(),v,index + 1),
674       Get(TypeWrapper<P3>(),v,index + 2),
675       Get(TypeWrapper<P4>(),v,index + 3)
676     );
677     Push(v,ret);
678     return 1;
679   }
680 
681   template<typename P1,typename P2,typename P3,typename P4,typename P5>
682   static SQInteger Call(RT (*func)(P1,P2,P3,P4,P5),HSQUIRRELVM v,SQInteger index) {
683     sq_argassert(1,index + 0);
684     sq_argassert(2,index + 1);
685     sq_argassert(3,index + 2);
686     sq_argassert(4,index + 3);
687     sq_argassert(5,index + 4);
688     RT ret = func(
689       Get(TypeWrapper<P1>(),v,index + 0),
690       Get(TypeWrapper<P2>(),v,index + 1),
691       Get(TypeWrapper<P3>(),v,index + 2),
692       Get(TypeWrapper<P4>(),v,index + 3),
693       Get(TypeWrapper<P5>(),v,index + 4)
694     );
695     Push(v,ret);
696     return 1;
697   }
698 
699   template<typename P1,typename P2,typename P3,typename P4,typename P5,typename P6>
700   static SQInteger Call(RT (*func)(P1,P2,P3,P4,P5,P6),HSQUIRRELVM v,SQInteger index) {
701     sq_argassert(1,index + 0);
702     sq_argassert(2,index + 1);
703     sq_argassert(3,index + 2);
704     sq_argassert(4,index + 3);
705     sq_argassert(5,index + 4);
706     sq_argassert(6,index + 5);
707     RT ret = func(
708       Get(TypeWrapper<P1>(),v,index + 0),
709       Get(TypeWrapper<P2>(),v,index + 1),
710       Get(TypeWrapper<P3>(),v,index + 2),
711       Get(TypeWrapper<P4>(),v,index + 3),
712       Get(TypeWrapper<P5>(),v,index + 4),
713       Get(TypeWrapper<P6>(),v,index + 5)
714     );
715     Push(v,ret);
716     return 1;
717   }
718 
719   template<typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7>
720   static SQInteger Call(RT (*func)(P1,P2,P3,P4,P5,P6,P7),HSQUIRRELVM v,SQInteger index) {
721     sq_argassert(1,index + 0);
722     sq_argassert(2,index + 1);
723     sq_argassert(3,index + 2);
724     sq_argassert(4,index + 3);
725     sq_argassert(5,index + 4);
726     sq_argassert(6,index + 5);
727     sq_argassert(7,index + 6);
728     RT ret = func(
729       Get(TypeWrapper<P1>(),v,index + 0),
730       Get(TypeWrapper<P2>(),v,index + 1),
731       Get(TypeWrapper<P3>(),v,index + 2),
732       Get(TypeWrapper<P4>(),v,index + 3),
733       Get(TypeWrapper<P5>(),v,index + 4),
734       Get(TypeWrapper<P6>(),v,index + 5),
735       Get(TypeWrapper<P7>(),v,index + 6)
736     );
737     Push(v,ret);
738     return 1;
739   }
740 
741   // === Member Function calls ===
742 
743   template <typename Callee>
744   static SQInteger Call(Callee & callee,RT (Callee::*func)(),HSQUIRRELVM v,SQInteger /*index*/) {
745     RT ret = (callee.*func)();
746     Push(v,ret);
747     return 1;
748   }
749 
750   template <typename Callee,typename P1>
751   static SQInteger Call(Callee & callee,RT (Callee::*func)(P1),HSQUIRRELVM v,SQInteger index) {
752     sq_argassert(1,index + 0);
753     RT ret = (callee.*func)(
754       Get(TypeWrapper<P1>(),v,index + 0)
755     );
756     Push(v,ret);
757     return 1;
758   }
759 
760   template<typename Callee,typename P1,typename P2>
761   static SQInteger Call(Callee & callee,RT (Callee::*func)(P1,P2),HSQUIRRELVM v,SQInteger index) {
762     sq_argassert(1,index + 0);
763     sq_argassert(2,index + 1);
764     RT ret = (callee.*func)(
765       Get(TypeWrapper<P1>(),v,index + 0),
766       Get(TypeWrapper<P2>(),v,index + 1)
767     );
768     Push(v,ret);
769     return 1;
770   }
771 
772   template<typename Callee,typename P1,typename P2,typename P3>
773   static SQInteger Call(Callee & callee,RT (Callee::*func)(P1,P2,P3),HSQUIRRELVM v,SQInteger index) {
774     sq_argassert(1,index + 0);
775     sq_argassert(2,index + 1);
776     sq_argassert(3,index + 2);
777     RT ret = (callee.*func)(
778       Get(TypeWrapper<P1>(),v,index + 0),
779       Get(TypeWrapper<P2>(),v,index + 1),
780       Get(TypeWrapper<P3>(),v,index + 2)
781     );
782     Push(v,ret);
783     return 1;
784   }
785 
786   template<typename Callee,typename P1,typename P2,typename P3,typename P4>
787   static SQInteger Call(Callee & callee,RT (Callee::*func)(P1,P2,P3,P4),HSQUIRRELVM v,SQInteger index) {
788     sq_argassert(1,index + 0);
789     sq_argassert(2,index + 1);
790     sq_argassert(3,index + 2);
791     sq_argassert(4,index + 3);
792     RT ret = (callee.*func)(
793       Get(TypeWrapper<P1>(),v,index + 0),
794       Get(TypeWrapper<P2>(),v,index + 1),
795       Get(TypeWrapper<P3>(),v,index + 2),
796       Get(TypeWrapper<P4>(),v,index + 3)
797     );
798     Push(v,ret);
799     return 1;
800   }
801 
802   template<typename Callee,typename P1,typename P2,typename P3,typename P4,typename P5>
803   static SQInteger Call(Callee & callee,RT (Callee::*func)(P1,P2,P3,P4,P5),HSQUIRRELVM v,SQInteger index) {
804     sq_argassert(1,index + 0);
805     sq_argassert(2,index + 1);
806     sq_argassert(3,index + 2);
807     sq_argassert(4,index + 3);
808     sq_argassert(5,index + 4);
809     RT ret = (callee.*func)(
810       Get(TypeWrapper<P1>(),v,index + 0),
811       Get(TypeWrapper<P2>(),v,index + 1),
812       Get(TypeWrapper<P3>(),v,index + 2),
813       Get(TypeWrapper<P4>(),v,index + 3),
814       Get(TypeWrapper<P5>(),v,index + 4)
815     );
816     Push(v,ret);
817     return 1;
818   }
819 
820   template<typename Callee,typename P1,typename P2,typename P3,typename P4,typename P5,typename P6>
821   static SQInteger Call(Callee & callee,RT (Callee::*func)(P1,P2,P3,P4,P5,P6),HSQUIRRELVM v,SQInteger index) {
822     sq_argassert(1,index + 0);
823     sq_argassert(2,index + 1);
824     sq_argassert(3,index + 2);
825     sq_argassert(4,index + 3);
826     sq_argassert(5,index + 4);
827     sq_argassert(6,index + 5);
828     RT ret = (callee.*func)(
829       Get(TypeWrapper<P1>(),v,index + 0),
830       Get(TypeWrapper<P2>(),v,index + 1),
831       Get(TypeWrapper<P3>(),v,index + 2),
832       Get(TypeWrapper<P4>(),v,index + 3),
833       Get(TypeWrapper<P5>(),v,index + 4),
834       Get(TypeWrapper<P6>(),v,index + 5)
835     );
836     Push(v,ret);
837     return 1;
838   }
839 
840   template<typename Callee,typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7>
841   static SQInteger Call(Callee & callee,RT (Callee::*func)(P1,P2,P3,P4,P5,P6,P7),HSQUIRRELVM v,SQInteger index) {
842     sq_argassert(1,index + 0);
843     sq_argassert(2,index + 1);
844     sq_argassert(3,index + 2);
845     sq_argassert(4,index + 3);
846     sq_argassert(5,index + 4);
847     sq_argassert(6,index + 5);
848     sq_argassert(7,index + 6);
849     RT ret = (callee.*func)(
850       Get(TypeWrapper<P1>(),v,index + 0),
851       Get(TypeWrapper<P2>(),v,index + 1),
852       Get(TypeWrapper<P3>(),v,index + 2),
853       Get(TypeWrapper<P4>(),v,index + 3),
854       Get(TypeWrapper<P5>(),v,index + 4),
855       Get(TypeWrapper<P6>(),v,index + 5),
856       Get(TypeWrapper<P7>(),v,index + 6)
857     );
858     Push(v,ret);
859     return 1;
860   }
861 
862 #ifdef SQPLUS_CONST_OPT
863 #define SQPLUS_CALL_CONST_MFUNC_RET0
864 #include "SqPlusConst.h"
865 #endif
866 };
867 
868 // === No return value variants ===
869 
870 template<>
871 struct ReturnSpecialization<void> {
872 
873   // === Standard function calls ===
874 
875   static SQInteger Call(void (*func)(),HSQUIRRELVM v,SQInteger /*index*/) {
876 		(void)v;
877 		func();
878 		return 0;
879 	}
880 
881 	template<typename P1>
882 	static SQInteger Call(void (*func)(P1),HSQUIRRELVM v,SQInteger index) {
883     sq_argassert(1,index + 0);
884 		func(
885 			Get(TypeWrapper<P1>(),v,index + 0)
886 		);
887 		return 0;
888 	}
889 
890 	template<typename P1,typename P2>
891 	static SQInteger Call(void (*func)(P1,P2),HSQUIRRELVM v,SQInteger index) {
892     sq_argassert(1,index + 0);
893     sq_argassert(2,index + 1);
894 		func(
895 			Get(TypeWrapper<P1>(),v,index + 0),
896 			Get(TypeWrapper<P2>(),v,index + 1)
897 		);
898 		return 0;
899 	}
900 
901   template<typename P1,typename P2,typename P3>
902   static SQInteger Call(void (*func)(P1,P2,P3),HSQUIRRELVM v,SQInteger index) {
903     sq_argassert(1,index + 0);
904     sq_argassert(2,index + 1);
905     sq_argassert(3,index + 2);
906     func(
907       Get(TypeWrapper<P1>(),v,index + 0),
908       Get(TypeWrapper<P2>(),v,index + 1),
909       Get(TypeWrapper<P3>(),v,index + 2)
910     );
911     return 0;
912   }
913 
914   template<typename P1,typename P2,typename P3,typename P4>
915   static SQInteger Call(void (*func)(P1,P2,P3,P4),HSQUIRRELVM v,SQInteger index) {
916     sq_argassert(1,index + 0);
917     sq_argassert(2,index + 1);
918     sq_argassert(3,index + 2);
919     sq_argassert(4,index + 3);
920     func(
921       Get(TypeWrapper<P1>(),v,index + 0),
922       Get(TypeWrapper<P2>(),v,index + 1),
923       Get(TypeWrapper<P3>(),v,index + 2),
924       Get(TypeWrapper<P4>(),v,index + 3)
925     );
926     return 0;
927   }
928 
929   template<typename P1,typename P2,typename P3,typename P4,typename P5>
930   static SQInteger Call(void (*func)(P1,P2,P3,P4,P5),HSQUIRRELVM v,SQInteger index) {
931     sq_argassert(1,index + 0);
932     sq_argassert(2,index + 1);
933     sq_argassert(3,index + 2);
934     sq_argassert(4,index + 3);
935     sq_argassert(5,index + 4);
936     func(
937       Get(TypeWrapper<P1>(),v,index + 0),
938       Get(TypeWrapper<P2>(),v,index + 1),
939       Get(TypeWrapper<P3>(),v,index + 2),
940       Get(TypeWrapper<P4>(),v,index + 3),
941       Get(TypeWrapper<P5>(),v,index + 4)
942     );
943     return 0;
944   }
945 
946   template<typename P1,typename P2,typename P3,typename P4,typename P5,typename P6>
947   static SQInteger Call(void (*func)(P1,P2,P3,P4,P5,P6),HSQUIRRELVM v,SQInteger index) {
948     sq_argassert(1,index + 0);
949     sq_argassert(2,index + 1);
950     sq_argassert(3,index + 2);
951     sq_argassert(4,index + 3);
952     sq_argassert(5,index + 4);
953     sq_argassert(6,index + 5);
954     func(
955       Get(TypeWrapper<P1>(),v,index + 0),
956       Get(TypeWrapper<P2>(),v,index + 1),
957       Get(TypeWrapper<P3>(),v,index + 2),
958       Get(TypeWrapper<P4>(),v,index + 3),
959       Get(TypeWrapper<P5>(),v,index + 4),
960       Get(TypeWrapper<P6>(),v,index + 5)
961     );
962     return 0;
963   }
964 
965   template<typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7>
966   static SQInteger Call(void (*func)(P1,P2,P3,P4,P5,P6,P7),HSQUIRRELVM v,SQInteger index) {
967     sq_argassert(1,index + 0);
968     sq_argassert(2,index + 1);
969     sq_argassert(3,index + 2);
970     sq_argassert(4,index + 3);
971     sq_argassert(5,index + 4);
972     sq_argassert(6,index + 5);
973     sq_argassert(7,index + 6);
974     func(
975       Get(TypeWrapper<P1>(),v,index + 0),
976       Get(TypeWrapper<P2>(),v,index + 1),
977       Get(TypeWrapper<P3>(),v,index + 2),
978       Get(TypeWrapper<P4>(),v,index + 3),
979       Get(TypeWrapper<P5>(),v,index + 4),
980       Get(TypeWrapper<P6>(),v,index + 5),
981       Get(TypeWrapper<P7>(),v,index + 6)
982     );
983     return 0;
984   }
985 
986   // === Member function calls ===
987 
988 	template<typename Callee>
989 	static SQInteger Call(Callee & callee,void (Callee::*func)(),HSQUIRRELVM,SQInteger /*index*/) {
990 		(callee.*func)();
991 		return 0;
992 	}
993 
994 	template<typename Callee,typename P1>
995 	static SQInteger Call(Callee & callee,void (Callee::*func)(P1),HSQUIRRELVM v,SQInteger index) {
996     sq_argassert(1,index + 0);
997 		(callee.*func)(
998 			Get(TypeWrapper<P1>(),v,index + 0)
999 		);
1000 		return 0;
1001 	}
1002 
1003 	template<typename Callee,typename P1,typename P2>
1004 	static SQInteger Call(Callee & callee,void (Callee::*func)(P1,P2),HSQUIRRELVM v,SQInteger index) {
1005     sq_argassert(1,index + 0);
1006     sq_argassert(2,index + 1);
1007 		(callee.*func)(
1008 			Get(TypeWrapper<P1>(),v,index + 0),
1009 			Get(TypeWrapper<P2>(),v,index + 1)
1010 		);
1011 		return 0;
1012 	}
1013 
1014 	template<typename Callee,typename P1,typename P2,typename P3>
1015 	static SQInteger Call(Callee & callee,void (Callee::*func)(P1,P2,P3),HSQUIRRELVM v,SQInteger index) {
1016     sq_argassert(1,index + 0);
1017     sq_argassert(2,index + 1);
1018     sq_argassert(3,index + 2);
1019 		(callee.*func)(
1020 			Get(TypeWrapper<P1>(),v,index + 0),
1021 			Get(TypeWrapper<P2>(),v,index + 1),
1022       Get(TypeWrapper<P3>(),v,index + 2)
1023 		);
1024 		return 0;
1025 	}
1026 
1027 	template<typename Callee,typename P1,typename P2,typename P3,typename P4>
1028 	static SQInteger Call(Callee & callee,void (Callee::*func)(P1,P2,P3,P4),HSQUIRRELVM v,SQInteger index) {
1029     sq_argassert(1,index + 0);
1030     sq_argassert(2,index + 1);
1031     sq_argassert(3,index + 2);
1032     sq_argassert(4,index + 3);
1033 		(callee.*func)(
1034 			Get(TypeWrapper<P1>(),v,index + 0),
1035 			Get(TypeWrapper<P2>(),v,index + 1),
1036       Get(TypeWrapper<P3>(),v,index + 2),
1037       Get(TypeWrapper<P4>(),v,index + 3)
1038 		);
1039 		return 0;
1040 	}
1041 
1042 	template<typename Callee,typename P1,typename P2,typename P3,typename P4,typename P5>
1043 	static SQInteger Call(Callee & callee,void (Callee::*func)(P1,P2,P3,P4,P5),HSQUIRRELVM v,SQInteger index) {
1044     sq_argassert(1,index + 0);
1045     sq_argassert(2,index + 1);
1046     sq_argassert(3,index + 2);
1047     sq_argassert(4,index + 3);
1048     sq_argassert(5,index + 4);
1049 		(callee.*func)(
1050 			Get(TypeWrapper<P1>(),v,index + 0),
1051 			Get(TypeWrapper<P2>(),v,index + 1),
1052       Get(TypeWrapper<P3>(),v,index + 2),
1053       Get(TypeWrapper<P4>(),v,index + 3),
1054       Get(TypeWrapper<P5>(),v,index + 4)
1055 		);
1056 		return 0;
1057 	}
1058 
1059 	template<typename Callee,typename P1,typename P2,typename P3,typename P4,typename P5,typename P6>
1060 	static SQInteger Call(Callee & callee,void (Callee::*func)(P1,P2,P3,P4,P5,P6),HSQUIRRELVM v,SQInteger index) {
1061     sq_argassert(1,index + 0);
1062     sq_argassert(2,index + 1);
1063     sq_argassert(3,index + 2);
1064     sq_argassert(4,index + 3);
1065     sq_argassert(5,index + 4);
1066     sq_argassert(6,index + 5);
1067 		(callee.*func)(
1068 			Get(TypeWrapper<P1>(),v,index + 0),
1069 			Get(TypeWrapper<P2>(),v,index + 1),
1070       Get(TypeWrapper<P3>(),v,index + 2),
1071       Get(TypeWrapper<P4>(),v,index + 3),
1072       Get(TypeWrapper<P5>(),v,index + 4),
1073       Get(TypeWrapper<P6>(),v,index + 5)
1074 		);
1075 		return 0;
1076 	}
1077 
1078 	template<typename Callee,typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7>
1079 	static SQInteger Call(Callee & callee,void (Callee::*func)(P1,P2,P3,P4,P5,P6,P7),HSQUIRRELVM v,SQInteger index) {
1080     sq_argassert(1,index + 0);
1081     sq_argassert(2,index + 1);
1082     sq_argassert(3,index + 2);
1083     sq_argassert(4,index + 3);
1084     sq_argassert(5,index + 4);
1085     sq_argassert(6,index + 5);
1086     sq_argassert(7,index + 6);
1087 		(callee.*func)(
1088 			Get(TypeWrapper<P1>(),v,index + 0),
1089 			Get(TypeWrapper<P2>(),v,index + 1),
1090       Get(TypeWrapper<P3>(),v,index + 2),
1091       Get(TypeWrapper<P4>(),v,index + 3),
1092       Get(TypeWrapper<P5>(),v,index + 4),
1093       Get(TypeWrapper<P6>(),v,index + 5),
1094       Get(TypeWrapper<P7>(),v,index + 6)
1095 		);
1096 		return 0;
1097 	}
1098 
1099 #ifdef SQPLUS_CONST_OPT
1100 #define SQPLUS_CALL_CONST_MFUNC_NORET
1101 #include "SqPlusConst.h"
1102 #endif
1103 
1104 };
1105 
1106 // === STANDARD Function return value specialized call handlers ===
1107 
1108 template<typename RT>
1109 SQInteger Call(RT (*func)(),HSQUIRRELVM v,SQInteger index) {
1110   return ReturnSpecialization<RT>::Call(func,v,index);
1111 }
1112 
1113 template<typename RT,typename P1>
1114 SQInteger Call(RT (*func)(P1),HSQUIRRELVM v,SQInteger index) {
1115   return ReturnSpecialization<RT>::Call(func,v,index);
1116 }
1117 
1118 template<typename RT,typename P1,typename P2>
1119 SQInteger Call(RT (*func)(P1,P2),HSQUIRRELVM v,SQInteger index) {
1120   return ReturnSpecialization<RT>::Call(func,v,index);
1121 }
1122 
1123 template<typename RT,typename P1,typename P2,typename P3>
1124 SQInteger Call(RT (*func)(P1,P2,P3),HSQUIRRELVM v,SQInteger index) {
1125   return ReturnSpecialization<RT>::Call(func,v,index);
1126 }
1127 
1128 template<typename RT,typename P1,typename P2,typename P3,typename P4>
1129 SQInteger Call(RT (*func)(P1,P2,P3,P4),HSQUIRRELVM v,SQInteger index) {
1130   return ReturnSpecialization<RT>::Call(func,v,index);
1131 }
1132 
1133 template<typename RT,typename P1,typename P2,typename P3,typename P4,typename P5>
1134 SQInteger Call(RT (*func)(P1,P2,P3,P4,P5),HSQUIRRELVM v,SQInteger index) {
1135   return ReturnSpecialization<RT>::Call(func,v,index);
1136 }
1137 
1138 template<typename RT,typename P1,typename P2,typename P3,typename P4,typename P5,typename P6>
1139 SQInteger Call(RT (*func)(P1,P2,P3,P4,P5,P6),HSQUIRRELVM v,SQInteger index) {
1140   return ReturnSpecialization<RT>::Call(func,v,index);
1141 }
1142 
1143 template<typename RT,typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7>
1144 SQInteger Call(RT (*func)(P1,P2,P3,P4,P5,P6,P7),HSQUIRRELVM v,SQInteger index) {
1145   return ReturnSpecialization<RT>::Call(func,v,index);
1146 }
1147 
1148 // === MEMBER Function return value specialized call handlers ===
1149 
1150 template<typename Callee,typename RT>
1151 SQInteger Call(Callee & callee, RT (Callee::*func)(),HSQUIRRELVM v,SQInteger index) {
1152   return ReturnSpecialization<RT>::Call(callee,func,v,index);
1153 }
1154 
1155 template<typename Callee,typename RT,typename P1>
1156 SQInteger Call(Callee & callee,RT (Callee::*func)(P1),HSQUIRRELVM v,SQInteger index) {
1157   return ReturnSpecialization<RT>::Call(callee,func,v,index);
1158 }
1159 
1160 template<typename Callee,typename RT,typename P1,typename P2>
1161 SQInteger Call(Callee & callee,RT (Callee::*func)(P1,P2),HSQUIRRELVM v,SQInteger index) {
1162   return ReturnSpecialization<RT>::Call(callee,func,v,index);
1163 }
1164 
1165 template<typename Callee,typename RT,typename P1,typename P2,typename P3>
1166 SQInteger Call(Callee & callee,RT (Callee::*func)(P1,P2,P3),HSQUIRRELVM v,SQInteger index) {
1167   return ReturnSpecialization<RT>::Call(callee,func,v,index);
1168 }
1169 
1170 template<typename Callee,typename RT,typename P1,typename P2,typename P3,typename P4>
1171 SQInteger Call(Callee & callee,RT (Callee::*func)(P1,P2,P3,P4),HSQUIRRELVM v,SQInteger index) {
1172   return ReturnSpecialization<RT>::Call(callee,func,v,index);
1173 }
1174 
1175 template<typename Callee,typename RT,typename P1,typename P2,typename P3,typename P4,typename P5>
1176 SQInteger Call(Callee & callee,RT (Callee::*func)(P1,P2,P3,P4,P5),HSQUIRRELVM v,SQInteger index) {
1177   return ReturnSpecialization<RT>::Call(callee,func,v,index);
1178 }
1179 
1180 template<typename Callee,typename RT,typename P1,typename P2,typename P3,typename P4,typename P5,typename P6>
1181 SQInteger Call(Callee & callee,RT (Callee::*func)(P1,P2,P3,P4,P5,P6),HSQUIRRELVM v,SQInteger index) {
1182   return ReturnSpecialization<RT>::Call(callee,func,v,index);
1183 }
1184 
1185 template<typename Callee,typename RT,typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7>
1186 SQInteger Call(Callee & callee,RT (Callee::*func)(P1,P2,P3,P4,P5,P6,P7),HSQUIRRELVM v,SQInteger index) {
1187   return ReturnSpecialization<RT>::Call(callee,func,v,index);
1188 }
1189 
1190 #ifdef SQPLUS_CONST_OPT
1191 #define SQPLUS_CALL_CONST_MFUNC_RET1
1192 #include "SqPlusConst.h"
1193 #endif
1194 
1195 // === Direct Call Standard Function handler ===
1196 
1197 template<typename Func>
1198 struct DirectCallFunction {
1199   static inline SQInteger Dispatch(HSQUIRRELVM v) {
1200     StackHandler sa(v);
1201     SQInteger paramCount = sa.GetParamCount();
1202     Func * func = (Func *)sa.GetUserData(paramCount);
1203     return Call(*func,v,2);
1204   } // Dispatch
1205 };
1206 
1207 // === Direct Call Member Function handler ===
1208 
1209 template<typename Callee,typename Func>
1210 class DirectCallMemberFunction {
1211 public:
1212   static inline SQInteger Dispatch(HSQUIRRELVM v) {
1213     StackHandler sa(v);
1214     SQInteger paramCount = sa.GetParamCount();
1215     unsigned char * ud = (unsigned char *)sa.GetUserData(paramCount);
1216     // C::B patch: Handle invalid instance type here
1217     if (!*(Callee**)ud) {
1218       return sq_throwerror(v,sqT("Invalid Instance Type"));
1219     } // if
1220     return Call(**(Callee**)ud,*(Func*)(ud + sizeof(Callee*)),v,2);
1221   } // Dispatch
1222 };
1223 
1224 // === Direct Call Instance Member Function handler ===
1225 
1226 #define SQ_CLASS_OBJECT_TABLE_NAME sqT("__ot")
1227 #define SQ_CLASS_HIER_ARRAY sqT("__ca")
1228 
1229 template<typename Callee,typename Func>
1230 class DirectCallInstanceMemberFunction {
1231 public:
1232   static inline SQInteger Dispatch(HSQUIRRELVM v) {
1233     StackHandler sa(v);
1234     Callee * instance = (Callee *)sa.GetInstanceUp(1,0);
1235     SQInteger paramCount = sa.GetParamCount();
1236     Func * func = (Func *)sa.GetUserData(paramCount);
1237     // C::B patch: Let the compiler search (comment out the whole block)
1238 //#ifdef SQ_USE_CLASS_INHERITANCE
1239 //    SquirrelObject so(sa.GetObjectHandle(1)); // 'this'
1240 //    SQUserPointer typetag; so.GetTypeTag(&typetag);
1241 //    SQUserPointer calleeType = ClassType<Callee>::type();
1242 //    if (typetag != calleeType) {
1243 //      SquirrelObject typeTable = so.GetValue(SQ_CLASS_OBJECT_TABLE_NAME);
1244 //      instance = (Callee *)typeTable.GetUserPointer(INT_T((size_t)ClassType<Callee>::type())); // <TODO> 64-bit compatible version.
1245 //      if (!instance) {
1246 //        return sq_throwerror(v,sqT("Invalid Instance Type"));
1247 //      } // if
1248 //    } // if
1249 //#endif
1250     // C::B patch: If not instance -> return Ok anyways
1251     if (!instance)
1252       return SQ_OK;
1253     return Call(*instance,*func,v,2);
1254   } // Dispatch
1255 };
1256 
1257 // === Direct Call Instance Member Function Variable Argument handler ===
1258 
1259 template<typename Callee>
1260 class DirectCallInstanceMemberFunctionVarArgs {
1261 public:
1262   typedef SQInteger (Callee::*FuncType)(HSQUIRRELVM);
1263   static inline SQInteger Dispatch(HSQUIRRELVM v) {
1264     StackHandler sa(v);
1265     Callee * instance = (Callee *)sa.GetInstanceUp(1,0);
1266     SQInteger paramCount = sa.GetParamCount();
1267     FuncType func = *(FuncType *)sa.GetUserData(paramCount);
1268     // C::B patch: Let the compiler search (comment out the whole block)
1269 //#ifdef SQ_USE_CLASS_INHERITANCE
1270 //    SquirrelObject so(sa.GetObjectHandle(1)); // 'this'
1271 //    SQUserPointer typetag; so.GetTypeTag(&typetag);
1272 //    SQUserPointer calleeType = ClassType<Callee>::type();
1273 //    if (typetag != calleeType) {
1274 //      SquirrelObject typeTable = so.GetValue(SQ_CLASS_OBJECT_TABLE_NAME);
1275 //      instance = (Callee *)typeTable.GetUserPointer(INT_T((size_t)ClassType<Callee>::type())); // <TODO> 64-bit compatible version.
1276 //      if (!instance) {
1277 //        return sq_throwerror(v,sqT("Invalid Instance Type"));
1278 //      } // if
1279 //    } // if
1280 //#endif
1281     sq_poptop(v); // Remove UserData from stack: so sa.GetParamCount() returns actual param count.
1282     // C::B patch: If not instance -> return Ok anyways
1283     if (!instance)
1284       return SQ_OK;
1285     return (instance->*func)(v);
1286   } // Dispatch
1287 };
1288 
1289 // Code fragment useful for debugging new implementations.
1290 #if 0
1291 HSQOBJECT ho = sa.GetObjectHandle(paramCount);
1292 SquirrelObject so(ho);
1293 SQObjectType sot = so.GetType();
1294 #endif
1295 
1296 // === Standard function call ===
1297 
1298 template<typename Func>
1299 inline void sq_pushdirectclosure(HSQUIRRELVM v,Func func,SQUnsignedInteger nupvalues) {
1300   SQUserPointer up = sq_newuserdata(v,sizeof(func)); // Also pushed on stack.
1301   memcpy(up,&func,sizeof(func));
1302   sq_newclosure(v,DirectCallFunction<Func>::Dispatch,nupvalues+1);
1303 } // sq_pushdirectclosure
1304 
1305 // === Fixed Class pointer call (always calls with object pointer that was registered) ===
1306 
1307 template<typename Callee,typename Func>
1308 inline void sq_pushdirectclosure(HSQUIRRELVM v,const Callee & callee,Func func,SQUnsignedInteger nupvalues) {
1309   unsigned char * up = (unsigned char *)sq_newuserdata(v,sizeof(Callee*)+sizeof(func));  // Also pushed on stack.
1310   const SQUserPointer pCallee = (SQUserPointer)&callee;
1311   memcpy(up,&pCallee,sizeof(Callee*));
1312   memcpy(up + sizeof(Callee*),&func,sizeof(func));
1313   sq_newclosure(v,DirectCallMemberFunction<Callee,Func>::Dispatch,nupvalues+1);
1314 } // sq_pushdirectclosure
1315 
1316 // === Class Instance call: class pointer retrieved from script class instance ===
1317 
1318 template<typename Callee,typename Func>
1319 inline void sq_pushdirectinstanceclosure(HSQUIRRELVM v,const Callee & /*callee*/,Func func,SQUnsignedInteger nupvalues) {
1320   unsigned char * up = (unsigned char *)sq_newuserdata(v,sizeof(func));  // Also pushed on stack.
1321   memcpy(up,&func,sizeof(func));
1322   sq_newclosure(v,DirectCallInstanceMemberFunction<Callee,Func>::Dispatch,nupvalues+1);
1323 } // sq_pushdirectinstanceclosure
1324 
1325 // === Class Instance call: class pointer retrieved from script class instance (variable arguments) ===
1326 
1327 template<typename Callee>
1328 inline void sq_pushdirectinstanceclosurevarargs(HSQUIRRELVM v,const Callee & callee,SQInteger (Callee::*func)(HSQUIRRELVM),SQUnsignedInteger nupvalues) {
1329   unsigned char * up = (unsigned char *)sq_newuserdata(v,sizeof(func)); // Also pushed on stack.
1330   memcpy(up,&func,sizeof(func));
1331   sq_newclosure(v,DirectCallInstanceMemberFunctionVarArgs<Callee>::Dispatch,nupvalues+1);
1332 } // sq_pushdirectinstanceclosurevarargs
1333 
1334 // === Register a STANDARD function (table or class on stack) ===
1335 
1336 template<typename Func>
1337 inline void Register(HSQUIRRELVM v,Func func,const SQChar * name) {
1338   sq_pushstring(v,name,-1);
1339   sq_pushdirectclosure(v,func,0);
1340   sq_createslot(v,-3); // Stack is restored after this call (same state as before Register() call).
1341 } // Register
1342 
1343 // === Register a MEMBER function (table or class on stack) ===
1344 
1345 template<typename Callee,typename Func>
1346 inline void Register(HSQUIRRELVM v,Callee & callee,Func func,const SQChar * name) {
1347   sq_pushstring(v,name,-1);
1348   sq_pushdirectclosure(v,callee,func,0);
1349   sq_createslot(v,-3); // Stack is restored after this call (same state as before Register() call).
1350 } // Register
1351 
1352 // === Register a STANDARD global function (root table) ===
1353 
1354 template<typename Func>
1355 inline void RegisterGlobal(HSQUIRRELVM v,Func func,const SQChar * name) {
1356   sq_pushroottable(v);
1357   Register(v,func,name);
1358   sq_poptop(v); // Remove root table.
1359 } // RegisterGlobal
1360 
1361 template<typename Func>
1362 inline void RegisterGlobal(Func func,const SQChar * name) {
1363   RegisterGlobal(SquirrelVM::GetVMPtr(),func,name);
1364 } // RegisterGlobal
1365 
1366 // === Register a MEMBER global function (root table) ===
1367 
1368 template<typename Callee,typename Func>
1369 inline void RegisterGlobal(HSQUIRRELVM v,Callee & callee,Func func,const SQChar * name) {
1370   sq_pushroottable(v);
1371   Register(v,callee,func,name);
1372   sq_poptop(v); // Remove root table.
1373 } // RegisterGlobal
1374 
1375 template<typename Callee,typename Func>
1376 inline void RegisterGlobal(Callee & callee,Func func,const SQChar * name) {
1377   RegisterGlobal(SquirrelVM::GetVMPtr(),callee,func,name);
1378 } // RegisterGlobal
1379 
1380 // === Register a STANDARD function (hso is table or class) ===
1381 
1382 template<typename Func>
1383 inline void Register(HSQUIRRELVM v,HSQOBJECT hso,Func func,const SQChar * name) {
1384   sq_pushobject(v,hso);
1385   Register(v,func,name);
1386   sq_poptop(v); // Remove hso.
1387 } // Register
1388 
1389 // === Register a MEMBER function (hso is table or class) ===
1390 // === Fixed Class pointer call (always calls with object pointer that was registered) ===
1391 
1392 template<typename Callee,typename Func>
1393 inline void Register(HSQUIRRELVM v,HSQOBJECT hso,Callee & callee,Func func,const SQChar * name) {
1394   sq_pushobject(v,hso);
1395   Register(v,callee,func,name);
1396   sq_poptop(v); // Remove hso.
1397 } // Register
1398 
1399 // === Register an INSTANCE MEMBER function ===
1400 // === Class Instance call: class pointer retrieved from script class instance ===
1401 
1402 template<typename Callee,typename Func>
1403 inline void RegisterInstance(HSQUIRRELVM v,HSQOBJECT hclass,Callee & callee,Func func,const SQChar * name) {
1404   sq_pushobject(v,hclass);
1405   sq_pushstring(v,name,-1);
1406   sq_pushdirectinstanceclosure(v,callee,func,0);
1407   sq_createslot(v,-3);
1408   sq_poptop(v); // Remove hclass.
1409 } // RegisterInstance
1410 
1411 
1412 #ifdef _MSC_VER
1413 #pragma warning(disable : 4995) // Deprecated _snprintf
1414 #endif
1415 
1416 // === Register an INSTANCE MEMBER function Variable Arguments ===
1417 // typeMask: "*" means don't check parameters, typeMask=0 means function takes no arguments (and is type checked for that case).
1418 // All the other Squirrel type-masks are passed normally.
1419 
1420 template<typename Callee>
1421 inline void RegisterInstanceVarArgs(HSQUIRRELVM v,HSQOBJECT hclass,Callee & callee,SQInteger (Callee::*func)(HSQUIRRELVM),const SQChar * name,const SQChar * typeMask=sqT("*")) {
1422   sq_pushobject(v,hclass);
1423   sq_pushstring(v,name,-1);
1424   sq_pushdirectinstanceclosurevarargs(v,callee,func,0);
1425   SQChar tm[64];
1426   SQChar * ptm = tm;
1427   SQInteger numParams = SQ_MATCHTYPEMASKSTRING;
1428   if (typeMask) {
1429     if (typeMask[0] == '*') {
1430       ptm       = 0; // Variable args: don't check parameters.
1431 //      numParams = 0; // Clear SQ_MATCHTYPEMASKSTRING (does not mean match 0 params. See sq_setparamscheck()).
1432     } else {
1433       if (SCSNPRINTF(tm,sizeof(tm),sqT("x%s"),typeMask) < 0) { // Must be an instance.
1434         throw SquirrelError(sqT("RegisterInstanceVarArgs: typeMask string too long."));
1435       } // if
1436     } // if
1437   } else { // <TODO> Need to check object type on stack: table, class, instance, etc.
1438 //    _snprintf(tm,sizeof(tm),"x"); // instance.
1439     tm[0] = 'x';
1440     tm[1] = 0;
1441   } // if
1442   if (ptm) { // If ptm == 0, don't check type.
1443     sq_setparamscheck(v,numParams,ptm); // Determine arg count from type string.
1444   } // if
1445 #ifdef _DEBUG
1446   sq_setnativeclosurename(v,-1,name); // For debugging only.
1447 #endif
1448   sq_createslot(v,-3);
1449   sq_poptop(v); // Remove hclass.
1450 } // RegisterInstanceVarArgs
1451 
1452 #ifdef _MSC_VER
1453 #pragma warning(default : 4995)
1454 #endif
1455 
1456 // === Call Squirrel Functions from C/C++ ===
1457 // No type checking is performed for Squirrel functions as Squirrel types are dynamic:
1458 // Incoming types are passed unchanged to Squirrel functions. The parameter count is checked: an exception is thrown if mismatched.
1459 // Return values must match the RT template argument type, else an exception can be thrown on return.
1460 
1461 template<typename RT>
1462 struct SquirrelFunction {
1463   HSQUIRRELVM v;
1464   SquirrelObject object; // Table or class.
1465   SquirrelObject func;
1466   SquirrelFunction() : v(0) {}
1467   SquirrelFunction(HSQUIRRELVM _v,const SquirrelObject & _object,const SquirrelObject & _func) : v(_v), object(_object), func(_func) {}
1468   SquirrelFunction(const SquirrelObject & _object,const SquirrelObject & _func) : v(SquirrelVM::GetVMPtr()), object(_object), func(_func) {}
1469   SquirrelFunction(const SquirrelObject & _object,const SQChar * name) {
1470     v      = SquirrelVM::GetVMPtr();
1471     object = _object;
1472     func   = object.GetValue(name);
1473   }
1474   SquirrelFunction(const SQChar * name) {
1475     v      = SquirrelVM::GetVMPtr();
1476     object = SquirrelVM::GetRootTable();
1477     func   = object.GetValue(name);
1478   }
1479 
1480   // Release references and reset internal objects to null.
1481   void reset(void) {
1482     func.Reset();
1483     object.Reset();
1484   } // Reset
1485 
1486 #define SQPLUS_CHECK_FNCALL(res) if (!SQ_SUCCEEDED(res)) throw SquirrelError(sqT("SquirrelFunction<> call failed"))
1487 
1488   RT operator()(void) {
1489     sq_pushobject(v,func.GetObjectHandle());
1490     sq_pushobject(v,object.GetObjectHandle());
1491     SQPLUS_CHECK_FNCALL(sq_call(v,1,SQTrue,SQ_CALL_RAISE_ERROR));
1492     return GetRet(TypeWrapper<RT>(),v,-1);
1493   }
1494 
1495   template<typename P1>
1496   RT operator()(P1 p1) {
1497     sq_pushobject(v,func.GetObjectHandle());
1498     sq_pushobject(v,object.GetObjectHandle());
1499     Push(v,p1);
1500     SQPLUS_CHECK_FNCALL(sq_call(v,2,SQTrue,SQ_CALL_RAISE_ERROR));
1501     return GetRet(TypeWrapper<RT>(),v,-1);
1502   }
1503 
1504   template<typename P1,typename P2>
1505   RT operator()(P1 p1,P2 p2) {
1506     sq_pushobject(v,func.GetObjectHandle());
1507     sq_pushobject(v,object.GetObjectHandle());
1508     Push(v,p1);
1509     Push(v,p2);
1510     SQPLUS_CHECK_FNCALL(sq_call(v,3,SQTrue,SQ_CALL_RAISE_ERROR));
1511     return GetRet(TypeWrapper<RT>(),v,-1);
1512   }
1513 
1514   template<typename P1,typename P2,typename P3>
1515   RT operator()(P1 p1,P2 p2,P3 p3) {
1516     sq_pushobject(v,func.GetObjectHandle());
1517     sq_pushobject(v,object.GetObjectHandle());
1518     Push(v,p1);
1519     Push(v,p2);
1520     Push(v,p3);
1521     SQPLUS_CHECK_FNCALL(sq_call(v,4,SQTrue,SQ_CALL_RAISE_ERROR));
1522     return GetRet(TypeWrapper<RT>(),v,-1);
1523   }
1524 
1525   template<typename P1,typename P2,typename P3,typename P4>
1526   RT operator()(P1 p1,P2 p2,P3 p3,P4 p4) {
1527     sq_pushobject(v,func.GetObjectHandle());
1528     sq_pushobject(v,object.GetObjectHandle());
1529     Push(v,p1);
1530     Push(v,p2);
1531     Push(v,p3);
1532     Push(v,p4);
1533     SQPLUS_CHECK_FNCALL(sq_call(v,5,SQTrue,SQ_CALL_RAISE_ERROR));
1534     return GetRet(TypeWrapper<RT>(),v,-1);
1535   }
1536 
1537   template<typename P1,typename P2,typename P3,typename P4,typename P5>
1538   RT operator()(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5) {
1539     sq_pushobject(v,func.GetObjectHandle());
1540     sq_pushobject(v,object.GetObjectHandle());
1541     Push(v,p1);
1542     Push(v,p2);
1543     Push(v,p3);
1544     Push(v,p4);
1545     Push(v,p5);
1546     SQPLUS_CHECK_FNCALL(sq_call(v,6,SQTrue,SQ_CALL_RAISE_ERROR));
1547     return GetRet(TypeWrapper<RT>(),v,-1);
1548   }
1549 
1550   template<typename P1,typename P2,typename P3,typename P4,typename P5,typename P6>
1551   RT operator()(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5,P6 p6) {
1552     sq_pushobject(v,func.GetObjectHandle());
1553     sq_pushobject(v,object.GetObjectHandle());
1554     Push(v,p1);
1555     Push(v,p2);
1556     Push(v,p3);
1557     Push(v,p4);
1558     Push(v,p5);
1559     Push(v,p6);
1560     SQPLUS_CHECK_FNCALL(sq_call(v,7,SQTrue,SQ_CALL_RAISE_ERROR));
1561     return GetRet(TypeWrapper<RT>(),v,-1);
1562   }
1563 
1564   template<typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7>
1565   RT operator()(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5,P6 p6,P7 p7) {
1566     sq_pushobject(v,func.GetObjectHandle());
1567     sq_pushobject(v,object.GetObjectHandle());
1568     Push(v,p1);
1569     Push(v,p2);
1570     Push(v,p3);
1571     Push(v,p4);
1572     Push(v,p5);
1573     Push(v,p6);
1574     Push(v,p7);
1575     SQPLUS_CHECK_FNCALL(sq_call(v,8,SQTrue,SQ_CALL_RAISE_ERROR));
1576     return GetRet(TypeWrapper<RT>(),v,-1);
1577   }
1578 
1579 };
1580 
1581 // === Class/Struct registration ===
1582 
1583 #define SQ_DELETE_CLASS(CLASSTYPE) if (up) { CLASSTYPE * self = (CLASSTYPE *)up; delete self;} return 0
1584 #define SQ_DECLARE_RELEASE(CLASSTYPE) \
1585   static SQInteger release(SQUserPointer up, SQInteger /*size*/) { \
1586     SQ_DELETE_CLASS(CLASSTYPE); \
1587   }
1588 
1589 template<typename T>
1590 struct ReleaseClassPtrPtr {
1591   static SQInteger release(SQUserPointer up,SQInteger size) {
1592     if (up) {
1593       T ** self = (T **)up;
1594       delete *self;
1595     } // if
1596     return 0;
1597   } // release
1598 };
1599 
1600 template<typename T>
1601 struct ReleaseClassPtr {
1602   static SQInteger release(SQUserPointer up,SQInteger size) {
1603     if (up) {
1604       T * self = (T *)up;
1605       delete self;
1606     } // if
1607     return 0;
1608   } // release
1609 };
1610 
1611 BOOL_T CreateClass(HSQUIRRELVM v,SquirrelObject & newClass,SQUserPointer classType,const SQChar * name,const SQChar * baseName=0);
1612 
1613 #define SQ_ANCESTOR_CLASS_INDEX sqT("__ci")
1614 
1615 // Call PostConstruct() at the end of custom constructors.
1616 template<typename T>
1617 inline SQInteger PostConstruct(HSQUIRRELVM v,T * newClass,SQRELEASEHOOK hook) {
1618 #ifdef SQ_USE_CLASS_INHERITANCE
1619   StackHandler sa(v);
1620   HSQOBJECT ho = sa.GetObjectHandle(1); // OT_INSTANCE
1621   SquirrelObject instance(ho);
1622   INT_T classIndex = instance.GetValue(SQ_ANCESTOR_CLASS_INDEX).ToInteger();
1623   if (classIndex == -1) { // Is this the most-derived C/C++ class? If so, create all ancestors (if present).
1624 
1625     SquirrelObject newObjectTable = SquirrelVM::CreateTable();                 // 11/2/05: Create a new table for this instance.
1626     newObjectTable.SetUserPointer(INT_T((size_t)ClassType<T>::type()),newClass); // <TODO> 64-bit compatible version.
1627     instance.SetValue(SQ_CLASS_OBJECT_TABLE_NAME,newObjectTable);
1628 
1629     SquirrelObject classHierArray = instance.GetValue(SQ_CLASS_HIER_ARRAY);
1630     INT_T count = classHierArray.Len();
1631     if (count > 1) { // This will be true when more than one C/C++ class is in the hierarchy.
1632       --count; // Skip the most-derived class.
1633       for (INT_T i=0; i < count; i++) {
1634 #ifdef CPP_STYLE_INHERITANCE // Kamaitati's changes for C++ inheritance support. jcs 5/28/06
1635         SquirrelObject so = classHierArray.GetValue(i);
1636         sq_pushobject(v,so.GetObjectHandle());
1637         SQUserPointer typeTag;
1638         sq_gettypetag(v,-1,&typeTag);
1639         newObjectTable.SetUserPointer(INT_T(size_t(typeTag)),newClass);
1640         sq_poptop(v);
1641 #else
1642         instance.SetValue(SQ_ANCESTOR_CLASS_INDEX,i); // Store ancestor class index for recursive constructor calls to come.
1643         INT_T top = sq_gettop(v);
1644         SquirrelObject so = classHierArray.GetValue(i); // Need to create UserData struct: store pointer to class, set release hook.
1645         SquirrelObject func = so.GetValue(sqT("constructor"));
1646         sq_pushobject(v,func.GetObjectHandle());
1647         sq_pushobject(v,instance.GetObjectHandle()); // The 'instance' is the real Squirrel 'this' for all ancestors (as opposed to an instance created from the defining class, which does not happen).
1648         sq_call(v,1,SQFalse,SQ_CALL_RAISE_ERROR); // Call constructor: no arguments are passed other than the 'instance'.
1649         sq_settop(v,top);
1650 #endif
1651       } // for
1652       instance.SetValue(SQ_ANCESTOR_CLASS_INDEX,SquirrelObject()); // Store an OT_NULL object to free SQ_ANCESTOR_CLASS_INDEX var.
1653     } // if
1654   } else { // Ancestor: Construct class and set release hook.
1655 
1656     SquirrelObject objectTable = instance.GetValue(SQ_CLASS_OBJECT_TABLE_NAME); // 11/2/05: Get the existing object table.
1657     objectTable.SetUserPointer(INT_T((size_t)ClassType<T>::type()),newClass);     // <TODO> 64-bit compatible version.
1658 
1659     INT_T top = sq_gettop(v);
1660     T ** ud = (T **)sq_newuserdata(v,sizeof(T *)); // Create UserData and push onto stack.
1661     *ud = newClass;
1662     // C::B patch: Disable releasing of objects (due to private/protected dtors) (Note: This is evil, but no other possibility found.)
1663 //    sq_setreleasehook(v,-1,ReleaseClassPtrPtr<T>::release); // Set release hook for UserData on stack.
1664     SquirrelObject userData;
1665     userData.AttachToStackObject(-1);
1666     SquirrelObject classHierArray = instance.GetValue(SQ_CLASS_HIER_ARRAY);
1667     classHierArray.SetValue(classIndex,userData); // Replace the class entry with UserData: will be freed during most-derived class destruction.
1668     sq_settop(v,top);
1669     return TRUE;
1670   } // if
1671 #endif
1672   sq_setinstanceup(v,1,newClass);
1673   sq_setreleasehook(v,1,hook);
1674   return 1;
1675 } // PostConstruct
1676 
1677 template<typename T>
1678 struct ConstructReleaseClass {
1679   static SQInteger construct(HSQUIRRELVM v) {
1680     return PostConstruct<T>(v,new T(),release);
1681   } // construct
1682   // C::B patch: Add empty constructor
1683   static SQInteger no_construct(HSQUIRRELVM v) {
1684     return PostConstruct<T>(v,0,0);
1685   } // no_construct
1686   SQ_DECLARE_RELEASE(T)
1687 };
1688 
1689 template<typename T>
1690 inline SquirrelObject RegisterClassType(HSQUIRRELVM v,const SQChar * scriptClassName,const SQChar * baseScriptClassName=0) {
1691   SQInteger top = sq_gettop(v);
1692   SquirrelObject newClass;
1693   if (CreateClass(v,newClass,(SQUserPointer)ClassType<T>::type(),scriptClassName,baseScriptClassName)) {
1694     SquirrelVM::CreateFunction(newClass,&ConstructReleaseClass<T>::no_construct,sqT("constructor"));
1695 #ifdef SQ_USE_CLASS_INHERITANCE
1696     // <NOTE> New member vars cannot be added to instances (OT_INSTANCE): additions must occur on the defining class (OT_CLASS), before any instances are instantiated.
1697     if (!newClass.Exists(SQ_CLASS_OBJECT_TABLE_NAME)) { // Will always get table from most-derived registered class.
1698       SquirrelObject objectTable = SquirrelVM::CreateTable();
1699       newClass.SetValue(SQ_CLASS_OBJECT_TABLE_NAME,objectTable); // Constructors must add their 'this' pointer indexed by type to this table. See PostConstruct() above.
1700                                                                  // 11/2/05: This table will behave as a static global for each instance unless overwritten during construction (see PostConstruct() above).
1701     } // if
1702     SquirrelObject classHierArray;
1703     if (!newClass.Exists(SQ_CLASS_HIER_ARRAY)) {   // Will always get table from most-derived registered class.
1704       classHierArray = SquirrelVM::CreateArray(0); // The only constructor called will be the most-derived class: this array contains all classes in the hierarchy to be constructed.
1705       newClass.SetValue(SQ_CLASS_HIER_ARRAY,classHierArray);
1706     } else {
1707       classHierArray = newClass.GetValue(SQ_CLASS_HIER_ARRAY);
1708     } // if
1709     classHierArray.ArrayAppend(newClass);          // Add the class to the hierarchy array. The array values will be released and replaced with UserData to free created ancestor classes.
1710     // C::B patch for 64bit builds
1711     newClass.SetValue(SQ_ANCESTOR_CLASS_INDEX,(SQInteger)-1); // When the class hierarchy is created, this var will be used to help in recursively creating ancestor classes.
1712 #endif
1713   } // if
1714   sq_settop(v,top);
1715   return newClass;
1716 } // RegisterClassType
1717 
1718 // === Define and register a C++ class and its members for use with Squirrel ===
1719 // Constructors+destructors are automatically created. Custom constructors must use the
1720 // standard SQFUNCTION signature if variable argument types are required (overloads).
1721 // See testSqPlus2.cpp for examples.
1722 
1723 template<typename TClassType>
1724 struct SQClassDef {
1725   HSQUIRRELVM v;
1726   const SQChar * name;
1727   const SQChar * base;
1728   SquirrelObject newClass;
1729 
1730 #ifdef SQ_USE_CLASS_INHERITANCE
1731   // Optional base arg is the name of a base class to inherit from (must already be defined in the Squirrel VM).
1732   SQClassDef(HSQUIRRELVM _v,const SQChar * _name,const SQChar * _base=0) : v(_v), name(_name), base(_base) {
1733     newClass = RegisterClassType<TClassType>(v,name,base);
1734   }
1735   // Optional base arg is the name of a base class to inherit from (must already be defined in the Squirrel VM).
1736   SQClassDef(const SQChar * _name,const SQChar * _base=0) : name(_name), base(_base) {
1737     v = SquirrelVM::GetVMPtr();
1738     newClass = RegisterClassType<TClassType>(v,name,base);
1739   }
1740 #else
1741   SQClassDef(HSQUIRRELVM _v,const SQChar * _name) : v(_v), name(_name) {
1742     newClass = RegisterClassType<TClassType>(v,name);
1743   }
1744 
1745   SQClassDef(const SQChar * _name) : name(_name) {
1746     v = SquirrelVM::GetVMPtr();
1747     newClass = RegisterClassType<TClassType>(v,name);
1748   }
1749 #endif
1750 
1751   // C::B patch: Add empty constructor
1752   SQClassDef & emptyCtor() {
1753     SquirrelVM::CreateFunction(newClass,&ConstructReleaseClass<TClassType>::construct,sqT("constructor"));
1754     return *this;
1755   } // emptyCtor
1756 
1757   // Register a member function.
1758   template<typename Func>
1759   SQClassDef & func(Func pfunc,const SQChar * name_) {
1760     RegisterInstance(v,newClass.GetObjectHandle(),*(TClassType *)0,pfunc,name_);
1761     return *this;
1762   } // func
1763 
1764   // Register a variable-argument member function (supports variable+multiple return values).
1765   // typeMask: "*" means don't check parameters, typeMask=0 means function takes no arguments (and is type checked for that case).
1766   // All the other Squirrel type-masks are passed normally.
1767   template<typename Func>
1768   SQClassDef & funcVarArgs(Func pfunc,const SQChar * name_,const SQChar * typeMask=sqT("*")) {
1769     RegisterInstanceVarArgs(v,newClass.GetObjectHandle(),*(TClassType *)0,pfunc,name_,typeMask);
1770     return *this;
1771   } // funcVarArgs
1772 
1773   // === BEGIN static-member+global function registration ===
1774 
1775   // === This version is for static member functions only, such as custom constructors where 'this' is not yet valid ===
1776   // typeMask: "*" means don't check parameters, typeMask=0 means function takes no arguments (and is type checked for that case).
1777   // All the other Squirrel type-masks are passed normally.
1778 
1779   template<typename Func>
1780   SQClassDef & staticFuncVarArgs(Func pfunc,const SQChar * name_,const SQChar * typeMask=sqT("*")) {
1781     SquirrelVM::PushObject(newClass);
1782     SquirrelVM::CreateFunction(pfunc,name_,typeMask);
1783     SquirrelVM::Pop(1);
1784     return *this;
1785   } // staticFuncVarArgs
1786 
1787   // Register a standard global function (effectively embedding a global function in TClassType's script namespace: does not need or use a 'this' pointer).
1788   template<typename Func>
1789   SQClassDef & staticFunc(Func pfunc,const SQChar * name_) {
1790     Register(v,newClass.GetObjectHandle(),pfunc,name_);
1791     return *this;
1792   } // staticFunc
1793 
1794   // Register a function to a pre-allocated class/struct member function: will use callee's 'this' (effectively embedding a global function in TClassType's script namespace).
1795   template<typename Callee,typename Func>
1796   SQClassDef & staticFunc(Callee & callee,Func pfunc,const SQChar * name_) {
1797     Register(v,newClass.GetObjectHandle(),callee,pfunc,name_);
1798     return *this;
1799   } // staticFunc
1800 
1801   // === END static+global function registration ===
1802 
1803   // Register a member variable.
1804   template<typename VarType>
1805   SQClassDef & var(VarType TClassType::* pvar,const SQChar * name_,VarAccessType access=VAR_ACCESS_READ_WRITE) {
1806     struct CV {
1807       VarType TClassType::* var;
1808     } cv; // Cast Variable helper.
1809     cv.var = pvar;
1810     RegisterInstanceVariable(newClass,ClassType<TClassType>::type(),*(VarType **)&cv,name_,access);
1811     return *this;
1812   } // var
1813 
1814   // Register a member variable as a UserPointer (read only).
1815   template<typename VarType>
1816   SQClassDef & varAsUserPointer(VarType TClassType::* pvar,const SQChar * name_) {
1817     struct CV {
1818       VarType TClassType::* var;
1819     } cv; // Cast Variable helper.
1820     cv.var = pvar;
1821     RegisterInstanceVariable(newClass,ClassType<TClassType>::type(),*(SQAnything **)&cv,name_,VAR_ACCESS_READ_ONLY);
1822     return *this;
1823   } // varAsUserPointer
1824 
1825   template<typename VarType>
1826   SQClassDef & staticVar(VarType * pvar,const SQChar * name_,VarAccessType access=VAR_ACCESS_READ_WRITE) {
1827     struct CV {
1828       VarType * var;
1829     } cv; // Cast Variable helper.
1830     cv.var = pvar;
1831     RegisterInstanceVariable(newClass,ClassType<TClassType>::type(),*(VarType **)&cv,name_,VarAccessType(access|VAR_ACCESS_STATIC));
1832     return *this;
1833   } // staticVar
1834 
1835 #ifdef SQPLUS_CONST_OPT
1836 #define SQ_REG_CONST_STATIC_VAR
1837 #include "SqPlusConst.h"
1838 #endif
1839 
1840   // Register a constant (read-only in script, passed by value (only INT_T, FLOAT_T, or BOOL_T types)).
1841   template<typename ConstantType>
1842   SQClassDef & constant(ConstantType constant_,const SQChar * name_) {
1843     RegisterInstanceConstant(newClass,ClassType<TClassType>::type(),constant_,name_);
1844     return *this;
1845   } // constant
1846 
1847   // Register an enum as an integer (read-only in script).
1848   SQClassDef & enumInt(SQInteger constant_,const SQChar * name_) {
1849       RegisterInstanceConstant(newClass,ClassType<TClassType>::type(),constant_,name_);
1850       return *this;
1851   } // enumInt
1852 
1853 };
1854 
1855 // === BEGIN Function Call Handlers ===
1856 
1857 inline void Push(HSQUIRRELVM v,char value)               { sq_pushinteger(v,value); }
1858 inline void Push(HSQUIRRELVM v,unsigned char value)      { sq_pushinteger(v,value); }
1859 inline void Push(HSQUIRRELVM v,short value)              { sq_pushinteger(v,value); }
1860 inline void Push(HSQUIRRELVM v,unsigned short value)     { sq_pushinteger(v,value); }
1861 inline void Push(HSQUIRRELVM v,int value)                { sq_pushinteger(v,value); }
1862 inline void Push(HSQUIRRELVM v,unsigned int value)       { sq_pushinteger(v,value); }
1863 inline void Push(HSQUIRRELVM v,long value)               { sq_pushinteger(v,value); }
1864 inline void Push(HSQUIRRELVM v,long long value)          { sq_pushinteger(v,value); }
1865 inline void Push(HSQUIRRELVM v,unsigned long value)      { sq_pushinteger(v,value); }
1866 inline void Push(HSQUIRRELVM v,unsigned long long value) { sq_pushinteger(v,value); }
1867 inline void Push(HSQUIRRELVM v,double value)             { sq_pushfloat(v,(FLOAT_T)value); }
1868 inline void Push(HSQUIRRELVM v,float value)              { sq_pushfloat(v,(FLOAT_T)value); }
1869 inline void Push(HSQUIRRELVM v,const SQChar * value)     { sq_pushstring(v,value,-1); }
1870 inline void Push(HSQUIRRELVM v,const SquirrelNull &)     { sq_pushnull(v); }
1871 inline void Push(HSQUIRRELVM v,SQFUNCTION value)         { sq_pushuserpointer(v,(void*)value); }
1872 inline void Push(HSQUIRRELVM v,SQAnythingPtr value)      { sq_pushuserpointer(v,(void*)value); } // Cast to SQAnythingPtr instead of void * if USE_ARGUMENT_DEPENDANT_OVERLOADS can't be used by your compiler.
1873 inline void Push(HSQUIRRELVM v,SquirrelObject & so)      { sq_pushobject(v,so.GetObjectHandle()); }
1874 
1875 
1876 #define USE_ARGUMENT_DEPENDANT_OVERLOADS
1877 #ifdef USE_ARGUMENT_DEPENDANT_OVERLOADS
1878 #ifdef _MSC_VER
1879 #pragma warning (disable:4675) // Disable warning: "resolved overload was found by argument-dependent lookup" when class/struct pointers are used as function arguments.
1880 #endif
1881 // === BEGIN Argument Dependent Overloads ===
1882 inline void Push(HSQUIRRELVM v,bool value)                  { sq_pushbool(v,value); }               // Pass bool as SQInteger if USE_ARGUMENT_DEPENDANT_OVERLOADS can't be used by your compiler.
1883 inline void Push(HSQUIRRELVM v,const void * value)          { sq_pushuserpointer(v,(void*)value); } // Pass SQAnythingPtr instead of void * "                                             "
1884 inline void Push(HSQUIRRELVM v,const SQUserPointer & value) { sq_pushuserpointer(v,(void*)value); }
1885 // === END Argument Dependent Overloads ===
1886 #endif
1887 
1888 #define SQPLUS_CHECK_GET(res) if (!SQ_SUCCEEDED(res)) throw SquirrelError(sqT("sq_get*() failed (type error)"))
1889 
1890 inline bool	Match(TypeWrapper<bool>,HSQUIRRELVM v,SQInteger idx)               { return sq_gettype(v,idx) == OT_BOOL; }
1891 inline bool	Match(TypeWrapper<char>,HSQUIRRELVM v,SQInteger idx)               { return sq_gettype(v,idx) == OT_INTEGER; }
1892 inline bool	Match(TypeWrapper<unsigned char>,HSQUIRRELVM v, SQInteger idx)     { return sq_gettype(v,idx) == OT_INTEGER; }
1893 inline bool	Match(TypeWrapper<short>,HSQUIRRELVM v,SQInteger idx)              { return sq_gettype(v,idx) == OT_INTEGER; }
1894 inline bool	Match(TypeWrapper<unsigned short>,HSQUIRRELVM v,SQInteger idx)     { return sq_gettype(v,idx) == OT_INTEGER; }
1895 inline bool	Match(TypeWrapper<int>,HSQUIRRELVM v,SQInteger idx)                { return sq_gettype(v,idx) == OT_INTEGER; }
1896 inline bool	Match(TypeWrapper<unsigned int>,HSQUIRRELVM v,SQInteger idx)       { return sq_gettype(v,idx) == OT_INTEGER; }
1897 inline bool	Match(TypeWrapper<long>,HSQUIRRELVM v,SQInteger idx)               { return sq_gettype(v,idx) == OT_INTEGER; }
1898 inline bool Match(TypeWrapper<long long>,HSQUIRRELVM v,SQInteger idx)          { return sq_gettype(v,idx) == OT_INTEGER; }
1899 inline bool	Match(TypeWrapper<unsigned long>,HSQUIRRELVM v,SQInteger idx)      { return sq_gettype(v,idx) == OT_INTEGER; }
1900 inline bool Match(TypeWrapper<unsigned long long>,HSQUIRRELVM v,SQInteger idx) { return sq_gettype(v,idx) == OT_INTEGER; }
1901 inline bool	Match(TypeWrapper<float>,HSQUIRRELVM v,SQInteger idx)              { SQInteger type = sq_gettype(v,idx); return type == OT_FLOAT; }
1902 inline bool	Match(TypeWrapper<double>,HSQUIRRELVM v,SQInteger idx)             { SQInteger type = sq_gettype(v,idx); return type == OT_FLOAT; }
1903 inline bool	Match(TypeWrapper<const SQChar *>,HSQUIRRELVM v,SQInteger idx)     { return sq_gettype(v,idx) == OT_STRING; }
1904 inline bool	Match(TypeWrapper<HSQUIRRELVM>,HSQUIRRELVM /*v*/,SQInteger /*idx*/){ return true; } // See Get() for HSQUIRRELVM below (v is always present).
1905 inline bool	Match(TypeWrapper<void*>,HSQUIRRELVM v,SQInteger idx)              { return sq_gettype(v,idx) == OT_USERPOINTER; }
1906 inline bool	Match(TypeWrapper<SquirrelObject>,HSQUIRRELVM /*v*/,SQInteger /*idx*/) { return true; } // See sq_getstackobj(): always returns true.
1907 
1908 inline void               Get(TypeWrapper<void>,HSQUIRRELVM /*v*/,int)                      { ; }
1909 inline bool               Get(TypeWrapper<bool>,HSQUIRRELVM v,SQInteger idx)                { SQBool b; SQPLUS_CHECK_GET(sq_getbool(v,idx,&b)); return b != 0; }
1910 inline char               Get(TypeWrapper<char>,HSQUIRRELVM v,SQInteger idx)                { INT_T i; SQPLUS_CHECK_GET(sq_getinteger(v,idx,&i)); return static_cast<char>(i); }
1911 inline unsigned char      Get(TypeWrapper<unsigned char>,HSQUIRRELVM v,SQInteger idx)       { INT_T i; SQPLUS_CHECK_GET(sq_getinteger(v,idx,&i)); return static_cast<unsigned char>(i); }
1912 inline short              Get(TypeWrapper<short>,HSQUIRRELVM v,SQInteger idx)               { INT_T i; SQPLUS_CHECK_GET(sq_getinteger(v,idx,&i)); return static_cast<short>(i); }
1913 inline unsigned short     Get(TypeWrapper<unsigned short>,HSQUIRRELVM v,SQInteger idx)      { INT_T i; SQPLUS_CHECK_GET(sq_getinteger(v,idx,&i)); return static_cast<unsigned short>(i); }
1914 inline int                Get(TypeWrapper<int>,HSQUIRRELVM v,SQInteger idx)                 { INT_T i; SQPLUS_CHECK_GET(sq_getinteger(v,idx,&i)); return i; }
1915 inline unsigned int       Get(TypeWrapper<unsigned int>,HSQUIRRELVM v,SQInteger idx)        { INT_T i; SQPLUS_CHECK_GET(sq_getinteger(v,idx,&i)); return static_cast<unsigned int>(i); }
1916 inline long               Get(TypeWrapper<long>,HSQUIRRELVM v,SQInteger idx)                { INT_T i; SQPLUS_CHECK_GET(sq_getinteger(v,idx,&i)); return static_cast<long>(i); }
1917 inline long long          Get(TypeWrapper<long long>,HSQUIRRELVM v,SQInteger idx)           { INT_T i; SQPLUS_CHECK_GET(sq_getinteger(v,idx,&i)); return static_cast<long long>(i); }
1918 inline unsigned long      Get(TypeWrapper<unsigned long>,HSQUIRRELVM v,SQInteger idx)       { INT_T i; SQPLUS_CHECK_GET(sq_getinteger(v,idx,&i)); return static_cast<unsigned long>(i); }
1919 inline unsigned long long Get(TypeWrapper<unsigned long long>, HSQUIRRELVM v,SQInteger idx) { INT_T i; SQPLUS_CHECK_GET(sq_getinteger(v,idx,&i)); return static_cast<unsigned long long>(i); }
1920 inline float              Get(TypeWrapper<float>,HSQUIRRELVM v,SQInteger idx)               { FLOAT_T f; SQPLUS_CHECK_GET(sq_getfloat(v,idx,&f)); return f; }
1921 inline double             Get(TypeWrapper<double>,HSQUIRRELVM v,SQInteger idx)              { FLOAT_T f; SQPLUS_CHECK_GET(sq_getfloat(v,idx,&f)); return static_cast<double>(f); }
1922 inline const SQChar *     Get(TypeWrapper<const SQChar *>,HSQUIRRELVM v,SQInteger idx)      { const SQChar * s; SQPLUS_CHECK_GET(sq_getstring(v,idx,&s)); return s; }
1923 inline SquirrelNull       Get(TypeWrapper<SquirrelNull>,HSQUIRRELVM v,SQInteger idx)        { (void)v, (void)idx; return SquirrelNull();  }
1924 inline void *             Get(TypeWrapper<void *>,HSQUIRRELVM v,SQInteger idx)              { SQUserPointer p; SQPLUS_CHECK_GET(sq_getuserpointer(v,idx,&p)); return p; }
1925 inline HSQUIRRELVM        Get(TypeWrapper<HSQUIRRELVM>,HSQUIRRELVM v,SQInteger /*idx*/)     { sq_poptop(v); return v; } // sq_poptop(v): remove UserData from stack so GetParamCount() matches normal behavior.
1926 inline SquirrelObject     Get(TypeWrapper<SquirrelObject>,HSQUIRRELVM v,SQInteger idx)      { HSQOBJECT o; SQPLUS_CHECK_GET(sq_getstackobj(v,idx,&o)); return SquirrelObject(o); }
1927 
1928 #ifdef SQPLUS_SUPPORT_STD_STRING
1929 inline void Push(HSQUIRRELVM v,const std::string& value) { sq_pushstring(v,value.c_str(),-1); }
1930 inline bool Match(TypeWrapper<const std::string&>, HSQUIRRELVM v, SQInteger idx) { return sq_gettype(v,idx) == OT_STRING; }
1931 inline std::string Get(TypeWrapper<const std::string&>,HSQUIRRELVM v,SQInteger idx) { const SQChar * s; SQPLUS_CHECK_GET(sq_getstring(v,idx,&s)); return std::string(s); }
1932 #endif
1933 
1934 // Added jflanglois suggestion, 8/20/06. jcs
1935 #ifdef SQPLUS_SUPPORT_SQ_STD_STRING
1936 typedef std::basic_string<SQChar> sq_std_string;
1937 inline void Push(HSQUIRRELVM v,const sq_std_string & value) { sq_pushstring(v,value.c_str(),-1); }
1938 inline bool Match(TypeWrapper<const sq_std_string &>, HSQUIRRELVM v, SQInteger idx) { return sq_gettype(v,idx) == OT_STRING; }
1939 inline sq_std_string Get(TypeWrapper<const sq_std_string &>,HSQUIRRELVM v,SQInteger idx) { const SQChar * s; SQPLUS_CHECK_GET(sq_getstring(v,idx,&s)); return sq_std_string(s); }
1940 #endif
1941 
1942 // GetRet() restores the stack for SquirrelFunction<>() calls.
1943 template<typename RT>
1944 inline RT GetRet(TypeWrapper<RT>,HSQUIRRELVM v,SQInteger idx) { RT ret = Get(TypeWrapper<RT>(),v,idx); sq_pop(v,2); return ret; } // sq_pop(v,2): restore stack after function call.
1945 
1946 // Specialization to support void return type.
1947 inline void GetRet(TypeWrapper<void>,HSQUIRRELVM v,SQInteger /*idx*/) { sq_pop(v,2); }
1948 
1949 // === END Function Call Handlers ===
1950 
1951 // === Example SQClassDef usage (see testSqPlus2.cpp): ===
1952 
1953 #if 0
1954   SQClassDef<NewTestObj> sqClass(sqT("NewTestObj");
1955   sqClass.func(NewTestObj::newtestR1,sqT("newtestR1"));
1956   sqClass.var(&NewTestObj::val,sqT("val"));
1957   sqClass.var(&NewTestObj::s1,sqT("s1"));
1958   sqClass.var(&NewTestObj::s2,sqT("s2"));
1959   sqClass.funcVarArgs(&NewTestObj::multiArgs,sqT("multiArgs"));
1960 
1961 // Shorthand form:
1962 
1963   SQClassDef<NewTestObj>(sqT("NewTestObj").
1964     func(NewTestObj::newtestR1,sqT("newtestR1")).
1965     var(&NewTestObj::val,sqT("val")).
1966     var(&NewTestObj::s1,sqT("s1")).
1967     var(&NewTestObj::s2,sqT("s2")).
1968     funcVarArgs(NewTestObj::multiArgs,sqT("multiArgs"));
1969 #endif
1970 
1971 // === Macros for old style registration. SQClassDef registration is now easier to use (SQ_DECLARE_CLASS() is not needed) ===
1972 
1973 #define SQ_DECLARE_CLASS(CLASSNAME)                                  \
1974 static SQInteger _##CLASSNAME##_release(SQUserPointer up,SQInteger size) { \
1975   if (up) {                                                          \
1976     CLASSNAME * self = (CLASSNAME *)up;                              \
1977     delete self;                                                     \
1978   }                                                                  \
1979   return 0;                                                          \
1980 }                                                                    \
1981 static SQInteger _##CLASSNAME##_constructor(HSQUIRRELVM v) {               \
1982   CLASSNAME * pc = new CLASSNAME();                                  \
1983   sq_setinstanceup(v,1,pc);                                          \
1984   sq_setreleasehook(v,1,_##CLASSNAME##_release);                     \
1985   return 1;                                                          \
1986 }
1987 
1988 #define SQ_REGISTER_CLASS(CLASSNAME)                                 \
1989   RegisterClassType(SquirrelVM::GetVMPtr(),sqT(#CLASSNAME),_##CLASSNAME##_constructor)
1990 
1991 #define SQ_REGISTER_INSTANCE(NEWSQCLASS,CCLASS,FUNCNAME)             \
1992   RegisterInstance(SquirrelVM::GetVMPtr(),NEWSQCLASS.GetObjectHandle(),*(CCLASS *)0,&CCLASS::FUNCNAME,sqT(#FUNCNAME));
1993 
1994 #define SQ_REGISTER_INSTANCE_VARARGS(NEWSQCLASS,CCLASS,FUNCNAME)     \
1995   RegisterInstanceVarArgs(SquirrelVM::GetVMPtr(),NEWSQCLASS.GetObjectHandle(),*(CCLASS *)0,&CCLASS::FUNCNAME,sqT(#FUNCNAME));
1996 
1997 #define SQ_REGISTER_INSTANCE_VARIABLE(NEWSQCLASS,CCLASS,VARNAME)     \
1998   RegisterInstanceVariable(NEWSQCLASS,&((CCLASS *)0)->VARNAME,sqT(#VARNAME));
1999 
2000 #if defined(USE_ARGUMENT_DEPENDANT_OVERLOADS) && defined(_MSC_VER)
2001 #pragma warning (default:4675)
2002 #endif
2003 
2004 }; // namespace SqPlus
2005 
2006 #endif //_SQ_PLUS_H_
2007