PageRenderTime 60ms CodeModel.GetById 19ms 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

Large files files are truncated, but you can click here to view the full file

  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 STAND…

Large files files are truncated, but you can click here to view the full file