PageRenderTime 68ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/codeblocks-10.05-release/src/include/scripting/sqplus/sqplus.h

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