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)© } 403 static CopyVarFunc getCopyFunc(void) { return (CopyVarFunc)© } 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