Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2025 lines
79 KiB

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