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.
16
#include <malloc/malloc.h>
18
// C::B patch: support for FreeBSD
26
#if defined(_MSC_VER) || defined(__BORLANDC__)
29
#define SCSNPRINTF _snprintf
32
#define SCSNPRINTF _snwprintf
36
// C::B patch: Convert conflicting _T() to sqT() --> applies to nearly *all* files!
39
#define SCSNPRINTF snprintf
40
#include <stdio.h> // for snprintf
45
#define SQ_CALL_RAISE_ERROR SQTrue
47
#define SQ_CALL_RAISE_ERROR SQFalse
52
// C::B patch: so it builds on 64bit, ecapsulate bool/int/float using Squirrel types (this patch applies everywhere, where threse types are used)
53
typedef SQInteger BOOL_T;
54
typedef SQInteger INT_T;
55
typedef SQFloat FLOAT_T;
59
#include "SquirrelObject.h"
60
#include "SquirrelVM.h"
61
#include "SquirrelBindingsUtils.h"
65
// === Class Inheritance Support ===
66
// Inheritance in Squirrel allows one class to inherit a base class's functions and variables.
67
// Variables are merged: if Derived has a var name 'val' and Base has a var of the same name,
68
// the resulting var 'val' will take Derived's initialization value.
69
// Functions are not merged, and can be called via Squirrel scoping rules.
71
// Define SQ_USE_CLASS_INHERITANCE to enable class inheritance support
72
// (requires slightly more memory and adds some CPU overhead).
73
// Can also be useful for debugging, as class type information is checked before
74
// dispatching instance function calls and before accessing instance member variables.
75
#define SQ_USE_CLASS_INHERITANCE
77
// Comment out to turn off instance type info support (to save a small amount of memory).
78
#define SQ_SUPPORT_INSTANCE_TYPE_INFO
80
// === Constant argument and constant member function support ===
81
// Define SQPLUS_CONST_OPT before including SqPlus.h for constant argument + constant member function support.
82
// C::B patch: Enable this option
83
#define SQPLUS_CONST_OPT
85
// === Uncomment to support std::string ===
86
//#define SQPLUS_SUPPORT_STD_STRING
88
// === Uncomment to support typedef std::basic_string<SQChar> sq_std_string ===
89
//#define SQPLUS_SUPPORT_SQ_STD_STRING
91
// === Uncomment to support NULL INSTANCE arguments ===
92
//#define SQPLUS_SUPPORT_NULL_INSTANCES
94
// === Uncomment to support C++ style inheritance
95
#define CPP_STYLE_INHERITANCE
97
// === Uncomment to skip sq_argassert() ===
98
//#define SQ_SKIP_ARG_ASSERT
100
template<class T> struct TypeWrapper {};
101
struct SquirrelNull {};
102
struct SQAnything { void * anything; }; // Needed for binding pointers to variables (cannot dereference void *).
103
typedef SQAnything * SQAnythingPtr;
104
typedef SQChar * SQCharPtr;
106
// === Do not use directly: use one of the predefined sizes below ===
108
struct ScriptStringVarBase {
109
//const unsigned char MaxLength; // Real length is MaxLength+1.
110
const SQInteger MaxLength; // C::B patch- to eliminate compiler warning
112
ScriptStringVarBase(SQInteger _MaxLength) : MaxLength(_MaxLength) {}
113
operator SQChar * () { return &s[0]; }
114
operator void * () { return (void *)&s[0]; }
115
const SQChar * operator = (const SQChar * _s) {
116
return safeStringCopy(s,_s,MaxLength);
118
// Special safe string copy where MaxLength is 1 less than true buffer length.
119
// strncpy() pads out nulls for the full length of the buffer specified by MaxLength.
120
static inline SQChar * safeStringCopy(SQChar * d,const SQChar * s,SQInteger MaxLength) {
125
if (i == MaxLength) break;
127
d[i] = 0; // Null terminate.
132
// === Do not use directly: use one of the predefined sizes below ===
134
template<SQInteger MAXLENGTH> // MAXLENGTH is max printable characters (trailing NULL is accounted for in ScriptStringVarBase::s[1]).
135
struct ScriptStringVar : ScriptStringVarBase {
136
SQChar ps[MAXLENGTH];
137
ScriptStringVar() : ScriptStringVarBase(MAXLENGTH) {
140
ScriptStringVar(const SQChar * _s) : ScriptStringVarBase(MAXLENGTH) {
143
const SQChar * operator = (const SQChar * _s) {
144
return safeStringCopy(s,_s,MaxLength);
146
const SQChar * operator = (const ScriptStringVar & _s) {
147
return safeStringCopy(s,_s.s,MaxLength);
149
bool operator == (const ScriptStringVar & _s) {
150
return _strcmp(s,_s.s) == 0;
152
bool compareCaseInsensitive(const ScriptStringVar & _s) {
153
return _stricmp(s,_s.s) == 0;
157
// === Fixed size strings for scripting ===
159
typedef ScriptStringVar<8> ScriptStringVar8;
160
typedef ScriptStringVar<16> ScriptStringVar16;
161
typedef ScriptStringVar<32> ScriptStringVar32;
162
typedef ScriptStringVar<64> ScriptStringVar64;
163
typedef ScriptStringVar<128> ScriptStringVar128;
164
typedef ScriptStringVar<256> ScriptStringVar256;
166
// === Script Variable Types ===
168
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};
170
template <typename T>
172
const SQChar * typeName;
173
enum {TypeID=VAR_TYPE_NONE,Size=0};
176
// === Common Variable Types ===
179
struct TypeInfo<INT_T> {
180
const SQChar * typeName;
181
TypeInfo() : typeName(sqT("int")) {}
182
enum {TypeID=VAR_TYPE_INT,Size=sizeof(INT_T)};
183
operator ScriptVarType() { return ScriptVarType(TypeID); }
187
struct TypeInfo<FLOAT_T> {
188
const SQChar * typeName;
189
TypeInfo() : typeName(sqT("float")) {}
190
enum {TypeID=VAR_TYPE_FLOAT,Size=sizeof(FLOAT_T)};
191
operator ScriptVarType() { return ScriptVarType(TypeID); }
195
struct TypeInfo<bool> {
196
const SQChar * typeName;
197
TypeInfo() : typeName(sqT("bool")) {}
198
enum {TypeID=VAR_TYPE_BOOL,Size=sizeof(BOOL_T)};
199
operator ScriptVarType() { return ScriptVarType(TypeID); }
203
struct TypeInfo<SQUserPointer> {
204
const SQChar * typeName;
205
TypeInfo() : typeName(sqT("SQUserPointer")) {}
206
enum {TypeID=VAR_TYPE_USER_POINTER,Size=sizeof(SQUserPointer)};
207
operator ScriptVarType() { return ScriptVarType(TypeID); }
211
struct TypeInfo<SQAnything> {
212
const SQChar * typeName;
213
TypeInfo() : typeName(sqT("SQUserPointer")) {}
214
enum {TypeID=VAR_TYPE_USER_POINTER,Size=sizeof(SQUserPointer)};
215
operator ScriptVarType() { return ScriptVarType(TypeID); }
219
struct TypeInfo<const SQChar *> {
220
const SQChar * typeName;
221
TypeInfo() : typeName(sqT("const SQChar *")) {}
222
enum {TypeID=VAR_TYPE_CONST_STRING,Size=sizeof(const SQChar *)};
223
operator ScriptVarType() { return ScriptVarType(TypeID); }
227
struct TypeInfo<ScriptStringVarBase> {
228
const SQChar * typeName;
229
TypeInfo() : typeName(sqT("ScriptStringVarBase")) {}
230
enum {TypeID=VAR_TYPE_STRING,Size=sizeof(ScriptStringVarBase)};
231
operator ScriptVarType() { return ScriptVarType(TypeID); }
234
// === Fixed String Variants ===
237
struct TypeInfo<ScriptStringVar8> {
238
const SQChar * typeName;
239
TypeInfo() : typeName(sqT("ScriptStringVar8")) {}
240
enum {TypeID=VAR_TYPE_STRING,Size=sizeof(ScriptStringVar8)};
241
operator ScriptVarType() { return ScriptVarType(TypeID); }
245
struct TypeInfo<ScriptStringVar16> {
246
const SQChar * typeName;
247
TypeInfo() : typeName(sqT("ScriptStringVar16")) {}
248
enum {TypeID=VAR_TYPE_STRING,Size=sizeof(ScriptStringVar16)};
249
operator ScriptVarType() { return ScriptVarType(TypeID); }
253
struct TypeInfo<ScriptStringVar32> {
254
const SQChar * typeName;
255
TypeInfo() : typeName(sqT("ScriptStringVar32")) {}
256
enum {TypeID=VAR_TYPE_STRING,Size=sizeof(ScriptStringVar32)};
257
operator ScriptVarType() { return ScriptVarType(TypeID); }
261
struct TypeInfo<ScriptStringVar64> {
262
const SQChar * typeName;
263
TypeInfo() : typeName(sqT("ScriptStringVar64")) {}
264
enum {TypeID=VAR_TYPE_STRING,Size=sizeof(ScriptStringVar64)};
265
operator ScriptVarType() { return ScriptVarType(TypeID); }
269
struct TypeInfo<ScriptStringVar128> {
270
const SQChar * typeName;
271
TypeInfo() : typeName(sqT("ScriptStringVar128")) {}
272
enum {TypeID=VAR_TYPE_STRING,Size=sizeof(ScriptStringVar128)};
273
operator ScriptVarType() { return ScriptVarType(TypeID); }
277
struct TypeInfo<ScriptStringVar256> {
278
const SQChar * typeName;
279
TypeInfo() : typeName(sqT("ScriptStringVar256")) {}
280
enum {TypeID=VAR_TYPE_STRING,Size=sizeof(ScriptStringVar256)};
281
operator ScriptVarType() { return ScriptVarType(TypeID); }
284
enum VarAccessType {VAR_ACCESS_READ_WRITE=0,VAR_ACCESS_READ_ONLY=1<<0,VAR_ACCESS_CONSTANT=1<<1,VAR_ACCESS_STATIC=1<<2};
286
// See VarRef and ClassType<> below: for instance assignment.
287
typedef void (*CopyVarFunc)(void * dst,void * src);
289
// === Variable references for script access ===
291
#define SQ_PLUS_TYPE_TABLE sqT("__SqTypes")
294
// In this case 'offsetOrAddrOrConst' is simpler than using an anonymous union.
295
void * offsetOrAddrOrConst; // Instance member variable offset from 'this' pointer base (as size_t), or address if static variable (void *), or constant value.
296
ScriptVarType type; // Variable type (from enum above).
297
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.
298
CopyVarFunc copyFunc; // Function pointer to copy variables (for instance variables only).
299
//short size; // Currently for debugging only (size of item when pointer to item is dereferenced). Could be used for variable max string buffer length.
300
SQInteger size; // Currently for debugging only (size of item when pointer to item is dereferenced). Could be used for variable max string buffer length.
301
short access; // VarAccessType.
302
const SQChar * typeName; // Type name string (to create instances by name).
303
VarRef() : offsetOrAddrOrConst(0), type(VAR_TYPE_NONE), instanceType((SQUserPointer)-1), copyFunc(0), size(0), access(VAR_ACCESS_READ_WRITE) {}
304
VarRef(void * _offsetOrAddrOrConst, ScriptVarType _type, SQUserPointer _instanceType, CopyVarFunc _copyFunc, SQInteger _size,VarAccessType _access,const SQChar * _typeName) :
305
offsetOrAddrOrConst(_offsetOrAddrOrConst), type(_type), instanceType(_instanceType), copyFunc(_copyFunc), size(_size), access(_access), typeName(_typeName) {
306
#ifdef SQ_SUPPORT_INSTANCE_TYPE_INFO
307
SquirrelObject typeTable = SquirrelVM::GetRootTable().GetValue(SQ_PLUS_TYPE_TABLE);
308
if (typeTable.IsNull()) {
309
typeTable = SquirrelVM::CreateTable();
310
SquirrelObject root = SquirrelVM::GetRootTable();
311
root.SetValue(SQ_PLUS_TYPE_TABLE,typeTable);
313
typeTable.SetValue(INT_T((size_t)copyFunc),typeName);
318
typedef VarRef * VarRefPtr;
320
// Internal use only.
321
inline void getVarNameTag(SQChar * buff,INT_T maxSize,const SQChar * scriptName) {
322
// assert(maxSize > 3);
328
maxSize -= (2+1); // +1 = space for null.
330
while (scriptName[pos] && pos < maxSize) {
331
d[pos] = scriptName[pos];
334
d[pos] = 0; // null terminate.
336
SCSNPRINTF(buff,maxSize,sqT("_v%s"),scriptName);
340
// Internal use only.
341
SQInteger setVarFunc(HSQUIRRELVM v);
342
SQInteger getVarFunc(HSQUIRRELVM v);
343
SQInteger setInstanceVarFunc(HSQUIRRELVM v);
344
SQInteger getInstanceVarFunc(HSQUIRRELVM v);
346
// === BEGIN Helpers ===
348
inline void createTableSetGetHandlers(SquirrelObject & so) {
349
SquirrelObject delegate = so.GetDelegate();
350
if (!delegate.Exists(sqT("_set"))) {
351
delegate = SquirrelVM::CreateTable();
352
SquirrelVM::CreateFunction(delegate,setVarFunc,sqT("_set"),sqT("sn|b|s")); // String var name = number(SQInteger or float) or bool or string.
353
SquirrelVM::CreateFunction(delegate,getVarFunc,sqT("_get"),sqT("s")); // String var name.
354
so.SetDelegate(delegate);
356
} // createTableSetGetHandlers
358
inline VarRefPtr createVarRef(SquirrelObject & so,const SQChar * scriptVarName) {
360
ScriptStringVar256 scriptVarTagName; getVarNameTag(scriptVarTagName,sizeof(scriptVarTagName),scriptVarName);
361
if (!so.GetUserData(scriptVarTagName,(SQUserPointer *)&pvr)) {
362
so.NewUserData(scriptVarTagName,sizeof(*pvr));
363
if (!so.GetUserData(scriptVarTagName,(SQUserPointer *)&pvr)) throw SquirrelError(sqT("Could not create UserData."));
369
void validateConstantType(T /*constant*/) {
370
switch(TypeInfo<T>()) {
374
case VAR_TYPE_CONST_STRING:
377
throw SquirrelError(sqT("validateConstantType(): type must be INT, FLOAT, BOOL, or CONST CHAR *."));
379
} // validateConstantType
381
inline void createInstanceSetGetHandlers(SquirrelObject & so) {
382
if (!so.Exists(sqT("_set"))) {
383
SquirrelVM::CreateFunction(so,setInstanceVarFunc,sqT("_set"),sqT("sn|b|s|x")); // String var name = number(SQInteger or float) or bool or string or instance.
384
SquirrelVM::CreateFunction(so,getInstanceVarFunc,sqT("_get"),sqT("s")); // String var name.
386
} // createInstanceSetGetHandlers
388
// === END Helpers ===
390
// === Class Type Helper class: returns a unique number for each class type ===
394
static SQUserPointer type(void) { return (SQUserPointer)© }
395
static CopyVarFunc getCopyFunc(void) { return (CopyVarFunc)© }
396
static void copy(T * dst,T * src) {
401
// === Bind a global or pre-allocated (not instance) class member variable or constant (for tables only (not classes)) ===
404
void BindVariable(SquirrelObject & so,T * var,const SQChar * scriptVarName,VarAccessType access=VAR_ACCESS_READ_WRITE) {
405
VarRefPtr pvr = createVarRef(so,scriptVarName);
406
*pvr = VarRef(var,TypeInfo<T>(),0,ClassType<T>::getCopyFunc(),sizeof(*var),access,TypeInfo<T>().typeName);
407
createTableSetGetHandlers(so);
410
// === Bind a constant by value: INT_T, FLOAT_T, BOOL_T, or CONST CHAR * (for tables only (not classes)) ===
413
void BindConstant(SquirrelObject & so,T constant,const SQChar * scriptVarName) {
414
validateConstantType(constant);
415
VarRefPtr pvr = createVarRef(so,scriptVarName);
416
#if __cplusplus>=201103L
417
static_assert(sizeof(constant)<=sizeof(void*), "using larger type");
419
void *ptr = reinterpret_cast<void*>(constant);
420
*pvr = VarRef(ptr,TypeInfo<T>(),0,0,sizeof(constant),VAR_ACCESS_CONSTANT,TypeInfo<T>().typeName);
421
createTableSetGetHandlers(so);
425
void BindVariable(T * var,const SQChar * scriptVarName,VarAccessType access=VAR_ACCESS_READ_WRITE) {
426
SquirrelObject so = SquirrelVM::GetRootTable();
427
BindVariable(so,var,scriptVarName,access);
431
void BindConstant(T constant,const SQChar * scriptVarName) {
432
SquirrelObject so = SquirrelVM::GetRootTable();
433
BindConstant(so,constant,scriptVarName);
436
// === Register a class instance member variable or constant. var argument provides type and offset ( effectively &((ClassType *)0)->var ) ===
438
// classType is the type of the member variable's containing class.
440
void RegisterInstanceVariable(SquirrelObject & so,SQUserPointer classType,T * var,const SQChar * scriptVarName,VarAccessType access=VAR_ACCESS_READ_WRITE) {
441
VarRef * pvr = createVarRef(so,scriptVarName);
442
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.
443
*pvr = VarRef(offsetOrAddrOrConst,TypeInfo<T>(),classType,ClassType<T>::getCopyFunc(),sizeof(*var),access,TypeInfo<T>().typeName);
444
createInstanceSetGetHandlers(so);
445
} // RegisterInstanceVariable
448
void RegisterInstanceConstant(SquirrelObject & so,SQUserPointer classType,T constant,const SQChar * scriptVarName) {
449
validateConstantType(constant);
450
VarRef * pvr = createVarRef(so,scriptVarName);
454
} cv; // Cast Variable helper.
456
*pvr = VarRef(*(void **)&cv,TypeInfo<T>(),classType,0,sizeof(constant),VAR_ACCESS_CONSTANT,TypeInfo<T>().typeName);
457
createInstanceSetGetHandlers(so);
458
} // RegisterInstanceConstant
460
//////////////////////////////////////////////////////////////////////////
461
/////////// BEGIN Generalized Class/Struct Instance Support //////////////
462
//////////////////////////////////////////////////////////////////////////
464
//BOOL_T CreateNativeClassInstance(HSQUIRRELVM v,const SQChar * classname,SQUserPointer ud,SQRELEASEHOOK hook); // In SquirrelBindingUtils.cpp.
466
// Create native class instance and leave on stack.
467
inline BOOL_T CreateConstructNativeClassInstance(HSQUIRRELVM v,const SQChar * className) {
468
SQInteger oldtop = sq_gettop(v);
470
sq_pushstring(v,className,-1);
471
if (SQ_FAILED(sq_rawget(v,-2))) { // Get the class (created with sq_newclass()).
476
sq_remove(v,-3); // Remove the root table.
477
sq_push(v,1); // Push the 'this'.
478
#else // Kamaitati's change. 5/28/06 jcs.
479
sq_remove(v,-2); // Remove the root table.
480
sq_pushroottable(v); // Push the 'this'.
482
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).
486
sq_remove(v,-2); // Remove the class.
487
// SQInteger newtop = sq_gettop(v);
489
} // CreateConstructNativeClassInstance
491
// Create new instance, copy 'classToCopy', and store result on stack.
493
inline BOOL_T CreateCopyInstance(const SQChar * className,const T & classToCopy) {
494
HSQUIRRELVM v = SquirrelVM::GetVMPtr();
495
if (!CreateConstructNativeClassInstance(v,className)) {
499
sq_getinstanceup(v,-1,&up,ClassType<T>::type());
500
if (!up) return FALSE;
501
T * newClass = (T *)up;
502
*newClass = classToCopy; // <TODO> Optimized version that uses the copy constructor.
504
} // CreateCopyInstance
506
// Create a new copy of type 'className' and copy 'classToCopy', return result via SquirrelObject.
508
inline SquirrelObject NewClassCopy(const SQChar * className,const T & classToCopy) {
510
if (CreateCopyInstance(className,classToCopy)) {
511
ret.AttachToStackObject(-1);
512
sq_poptop(SquirrelVM::GetVMPtr());
514
throw SquirrelError(sqT("NewClassCopy(): could not create class"));
519
// Return a new class copy on the stack from a varArgs function call.
521
inline SQInteger ReturnCopy(HSQUIRRELVM v,const T & classToCopy) {
522
SquirrelObject so(NewClassCopy(GetTypeName(classToCopy),classToCopy));
523
return StackHandler(v).Return(so);
526
// Katsuaki Kawachi's GetInstance<> exception change. 6/27/06 jcs
528
// Get an instance of type T from the stack at idx (for function calls).
529
template<typename T,bool ExceptionOnError>
530
T * GetInstance(HSQUIRRELVM v,SQInteger idx) {
532
sq_getinstanceup(v,idx,&up,ClassType<T>::type());
533
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).
534
if (!up) throw SquirrelError(sqT("GetInstance: Invalid argument type"));
539
// NAME and macro changes from Ben's (Project5) forum post. 2/26/06 jcs
540
// Kamaitati's NULL_INSTANCE support. 5/28/06 jcs
542
#ifdef SQPLUS_SUPPORT_NULL_INSTANCES
544
#define DECLARE_INSTANCE_TYPE_NAME_(TYPE,NAME) namespace SqPlus { \
545
inline const SQChar * GetTypeName(const TYPE & /*n*/) { return sqT(#NAME); } \
546
inline void Push(HSQUIRRELVM v,TYPE * value) { \
547
if (!value) sq_pushnull(v); \
548
else if (!CreateNativeClassInstance(v,GetTypeName(*value),value,0)) \
549
throw SquirrelError(sqT("Push(): could not create INSTANCE (check registration name)")); } \
550
inline void Push(HSQUIRRELVM /*v*/,TYPE & value) { if (!CreateCopyInstance(GetTypeName(value),value)) throw SquirrelError(sqT("Push(): could not create INSTANCE copy (check registration name)")); } \
551
inline bool Match(TypeWrapper<TYPE &>,HSQUIRRELVM v,SQInteger idx) { return GetInstance<TYPE,false>(v,idx) != NULL; } \
552
inline bool Match(TypeWrapper<TYPE *>,HSQUIRRELVM v,SQInteger idx) { \
553
return (sq_gettype(v,idx)==OT_NULL) || (GetInstance<TYPE,false>(v,idx) != NULL); } \
554
inline TYPE & Get(TypeWrapper<TYPE &>,HSQUIRRELVM v,SQInteger idx) { return *GetInstance<TYPE,true>(v,idx); } \
555
inline TYPE * Get(TypeWrapper<TYPE *>,HSQUIRRELVM v,SQInteger idx) { \
556
if (sq_gettype(v,idx)==OT_NULL) return NULL; \
557
return GetInstance<TYPE,true>(v,idx); } \
559
struct TypeInfo<TYPE> { \
560
const SQChar * typeName; \
561
TypeInfo() : typeName(sqT(#NAME)) {} \
562
enum {TypeID=VAR_TYPE_INSTANCE,Size=sizeof(TYPE)}; \
563
operator ScriptVarType() { return ScriptVarType(TypeID); } \
565
} // nameSpace SqPlus
569
#define DECLARE_INSTANCE_TYPE_NAME_(TYPE,NAME) namespace SqPlus { \
570
inline const SQChar * GetTypeName(const TYPE & /*n*/) { return sqT(#NAME); } \
571
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)")); } \
572
inline void Push(HSQUIRRELVM /*v*/,TYPE & value) { if (!CreateCopyInstance(GetTypeName(value),value)) throw SquirrelError(sqT("Push(): could not create INSTANCE copy (check registration name)")); } \
573
inline bool Match(TypeWrapper<TYPE &>,HSQUIRRELVM v,SQInteger idx) { return GetInstance<TYPE,false>(v,idx) != NULL; } \
574
inline bool Match(TypeWrapper<TYPE *>,HSQUIRRELVM v,SQInteger idx) { return GetInstance<TYPE,false>(v,idx) != NULL; } \
575
inline TYPE & Get(TypeWrapper<TYPE &>,HSQUIRRELVM v,SQInteger idx) { return *GetInstance<TYPE,true>(v,idx); } \
576
inline TYPE * Get(TypeWrapper<TYPE *>,HSQUIRRELVM v,SQInteger idx) { return GetInstance<TYPE,true>(v,idx); } \
578
struct TypeInfo<TYPE> { \
579
const SQChar * typeName; \
580
TypeInfo() : typeName(sqT(#NAME)) {} \
581
enum {TypeID=VAR_TYPE_INSTANCE,Size=sizeof(TYPE)}; \
582
operator ScriptVarType() { return ScriptVarType(TypeID); } \
584
} // nameSpace SqPlus
588
// 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.
589
#ifndef SQPLUS_CONST_OPT
590
#define DECLARE_INSTANCE_TYPE(TYPE) DECLARE_INSTANCE_TYPE_NAME_(TYPE,TYPE)
591
#define DECLARE_INSTANCE_TYPE_NAME(TYPE,NAME) DECLARE_INSTANCE_TYPE_NAME_(TYPE,NAME)
593
#define SQPLUS_DECLARE_INSTANCE_TYPE_CONST
594
#include "SqPlusConst.h"
597
//////////////////////////////////////////////////////////////////////////
598
//////////// END Generalized Class/Struct Instance Support ///////////////
599
//////////////////////////////////////////////////////////////////////////
601
#ifndef SQ_SKIP_ARG_ASSERT
602
#define sq_argassert(arg,_index_) if (!Match(TypeWrapper<P##arg>(),v,_index_)) return sq_throwerror(v,sqT("Incorrect function argument"))
604
#define sq_argassert(arg,_index_)
607
// === Return value variants ===
610
struct ReturnSpecialization {
612
// === Standard Function calls ===
614
static SQInteger Call(RT (*func)(),HSQUIRRELVM v,SQInteger /*index*/) {
620
template<typename P1>
621
static SQInteger Call(RT (*func)(P1),HSQUIRRELVM v,SQInteger index) {
622
sq_argassert(1,index + 0);
624
Get(TypeWrapper<P1>(),v,index + 0)
630
template<typename P1,typename P2>
631
static SQInteger Call(RT (*func)(P1,P2),HSQUIRRELVM v,SQInteger index) {
632
sq_argassert(1,index + 0);
633
sq_argassert(2,index + 1);
635
Get(TypeWrapper<P1>(),v,index + 0),
636
Get(TypeWrapper<P2>(),v,index + 1)
642
template<typename P1,typename P2,typename P3>
643
static SQInteger Call(RT (*func)(P1,P2,P3),HSQUIRRELVM v,SQInteger index) {
644
sq_argassert(1,index + 0);
645
sq_argassert(2,index + 1);
646
sq_argassert(3,index + 2);
648
Get(TypeWrapper<P1>(),v,index + 0),
649
Get(TypeWrapper<P2>(),v,index + 1),
650
Get(TypeWrapper<P3>(),v,index + 2)
656
template<typename P1,typename P2,typename P3,typename P4>
657
static SQInteger Call(RT (*func)(P1,P2,P3,P4),HSQUIRRELVM v,SQInteger index) {
658
sq_argassert(1,index + 0);
659
sq_argassert(2,index + 1);
660
sq_argassert(3,index + 2);
661
sq_argassert(4,index + 3);
663
Get(TypeWrapper<P1>(),v,index + 0),
664
Get(TypeWrapper<P2>(),v,index + 1),
665
Get(TypeWrapper<P3>(),v,index + 2),
666
Get(TypeWrapper<P4>(),v,index + 3)
672
template<typename P1,typename P2,typename P3,typename P4,typename P5>
673
static SQInteger Call(RT (*func)(P1,P2,P3,P4,P5),HSQUIRRELVM v,SQInteger index) {
674
sq_argassert(1,index + 0);
675
sq_argassert(2,index + 1);
676
sq_argassert(3,index + 2);
677
sq_argassert(4,index + 3);
678
sq_argassert(5,index + 4);
680
Get(TypeWrapper<P1>(),v,index + 0),
681
Get(TypeWrapper<P2>(),v,index + 1),
682
Get(TypeWrapper<P3>(),v,index + 2),
683
Get(TypeWrapper<P4>(),v,index + 3),
684
Get(TypeWrapper<P5>(),v,index + 4)
690
template<typename P1,typename P2,typename P3,typename P4,typename P5,typename P6>
691
static SQInteger Call(RT (*func)(P1,P2,P3,P4,P5,P6),HSQUIRRELVM v,SQInteger index) {
692
sq_argassert(1,index + 0);
693
sq_argassert(2,index + 1);
694
sq_argassert(3,index + 2);
695
sq_argassert(4,index + 3);
696
sq_argassert(5,index + 4);
697
sq_argassert(6,index + 5);
699
Get(TypeWrapper<P1>(),v,index + 0),
700
Get(TypeWrapper<P2>(),v,index + 1),
701
Get(TypeWrapper<P3>(),v,index + 2),
702
Get(TypeWrapper<P4>(),v,index + 3),
703
Get(TypeWrapper<P5>(),v,index + 4),
704
Get(TypeWrapper<P6>(),v,index + 5)
710
template<typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7>
711
static SQInteger Call(RT (*func)(P1,P2,P3,P4,P5,P6,P7),HSQUIRRELVM v,SQInteger index) {
712
sq_argassert(1,index + 0);
713
sq_argassert(2,index + 1);
714
sq_argassert(3,index + 2);
715
sq_argassert(4,index + 3);
716
sq_argassert(5,index + 4);
717
sq_argassert(6,index + 5);
718
sq_argassert(7,index + 6);
720
Get(TypeWrapper<P1>(),v,index + 0),
721
Get(TypeWrapper<P2>(),v,index + 1),
722
Get(TypeWrapper<P3>(),v,index + 2),
723
Get(TypeWrapper<P4>(),v,index + 3),
724
Get(TypeWrapper<P5>(),v,index + 4),
725
Get(TypeWrapper<P6>(),v,index + 5),
726
Get(TypeWrapper<P7>(),v,index + 6)
732
// === Member Function calls ===
734
template <typename Callee>
735
static SQInteger Call(Callee & callee,RT (Callee::*func)(),HSQUIRRELVM v,SQInteger /*index*/) {
736
RT ret = (callee.*func)();
741
template <typename Callee,typename P1>
742
static SQInteger Call(Callee & callee,RT (Callee::*func)(P1),HSQUIRRELVM v,SQInteger index) {
743
sq_argassert(1,index + 0);
744
RT ret = (callee.*func)(
745
Get(TypeWrapper<P1>(),v,index + 0)
751
template<typename Callee,typename P1,typename P2>
752
static SQInteger Call(Callee & callee,RT (Callee::*func)(P1,P2),HSQUIRRELVM v,SQInteger index) {
753
sq_argassert(1,index + 0);
754
sq_argassert(2,index + 1);
755
RT ret = (callee.*func)(
756
Get(TypeWrapper<P1>(),v,index + 0),
757
Get(TypeWrapper<P2>(),v,index + 1)
763
template<typename Callee,typename P1,typename P2,typename P3>
764
static SQInteger Call(Callee & callee,RT (Callee::*func)(P1,P2,P3),HSQUIRRELVM v,SQInteger index) {
765
sq_argassert(1,index + 0);
766
sq_argassert(2,index + 1);
767
sq_argassert(3,index + 2);
768
RT ret = (callee.*func)(
769
Get(TypeWrapper<P1>(),v,index + 0),
770
Get(TypeWrapper<P2>(),v,index + 1),
771
Get(TypeWrapper<P3>(),v,index + 2)
777
template<typename Callee,typename P1,typename P2,typename P3,typename P4>
778
static SQInteger Call(Callee & callee,RT (Callee::*func)(P1,P2,P3,P4),HSQUIRRELVM v,SQInteger index) {
779
sq_argassert(1,index + 0);
780
sq_argassert(2,index + 1);
781
sq_argassert(3,index + 2);
782
sq_argassert(4,index + 3);
783
RT ret = (callee.*func)(
784
Get(TypeWrapper<P1>(),v,index + 0),
785
Get(TypeWrapper<P2>(),v,index + 1),
786
Get(TypeWrapper<P3>(),v,index + 2),
787
Get(TypeWrapper<P4>(),v,index + 3)
793
template<typename Callee,typename P1,typename P2,typename P3,typename P4,typename P5>
794
static SQInteger Call(Callee & callee,RT (Callee::*func)(P1,P2,P3,P4,P5),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
sq_argassert(5,index + 4);
800
RT ret = (callee.*func)(
801
Get(TypeWrapper<P1>(),v,index + 0),
802
Get(TypeWrapper<P2>(),v,index + 1),
803
Get(TypeWrapper<P3>(),v,index + 2),
804
Get(TypeWrapper<P4>(),v,index + 3),
805
Get(TypeWrapper<P5>(),v,index + 4)
811
template<typename Callee,typename P1,typename P2,typename P3,typename P4,typename P5,typename P6>
812
static SQInteger Call(Callee & callee,RT (Callee::*func)(P1,P2,P3,P4,P5,P6),HSQUIRRELVM v,SQInteger index) {
813
sq_argassert(1,index + 0);
814
sq_argassert(2,index + 1);
815
sq_argassert(3,index + 2);
816
sq_argassert(4,index + 3);
817
sq_argassert(5,index + 4);
818
sq_argassert(6,index + 5);
819
RT ret = (callee.*func)(
820
Get(TypeWrapper<P1>(),v,index + 0),
821
Get(TypeWrapper<P2>(),v,index + 1),
822
Get(TypeWrapper<P3>(),v,index + 2),
823
Get(TypeWrapper<P4>(),v,index + 3),
824
Get(TypeWrapper<P5>(),v,index + 4),
825
Get(TypeWrapper<P6>(),v,index + 5)
831
template<typename Callee,typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7>
832
static SQInteger Call(Callee & callee,RT (Callee::*func)(P1,P2,P3,P4,P5,P6,P7),HSQUIRRELVM v,SQInteger index) {
833
sq_argassert(1,index + 0);
834
sq_argassert(2,index + 1);
835
sq_argassert(3,index + 2);
836
sq_argassert(4,index + 3);
837
sq_argassert(5,index + 4);
838
sq_argassert(6,index + 5);
839
sq_argassert(7,index + 6);
840
RT ret = (callee.*func)(
841
Get(TypeWrapper<P1>(),v,index + 0),
842
Get(TypeWrapper<P2>(),v,index + 1),
843
Get(TypeWrapper<P3>(),v,index + 2),
844
Get(TypeWrapper<P4>(),v,index + 3),
845
Get(TypeWrapper<P5>(),v,index + 4),
846
Get(TypeWrapper<P6>(),v,index + 5),
847
Get(TypeWrapper<P7>(),v,index + 6)
853
#ifdef SQPLUS_CONST_OPT
854
#define SQPLUS_CALL_CONST_MFUNC_RET0
855
#include "SqPlusConst.h"
859
// === No return value variants ===
862
struct ReturnSpecialization<void> {
864
// === Standard function calls ===
866
static SQInteger Call(void (*func)(),HSQUIRRELVM v,SQInteger /*index*/) {
872
template<typename P1>
873
static SQInteger Call(void (*func)(P1),HSQUIRRELVM v,SQInteger index) {
874
sq_argassert(1,index + 0);
876
Get(TypeWrapper<P1>(),v,index + 0)
881
template<typename P1,typename P2>
882
static SQInteger Call(void (*func)(P1,P2),HSQUIRRELVM v,SQInteger index) {
883
sq_argassert(1,index + 0);
884
sq_argassert(2,index + 1);
886
Get(TypeWrapper<P1>(),v,index + 0),
887
Get(TypeWrapper<P2>(),v,index + 1)
892
template<typename P1,typename P2,typename P3>
893
static SQInteger Call(void (*func)(P1,P2,P3),HSQUIRRELVM v,SQInteger index) {
894
sq_argassert(1,index + 0);
895
sq_argassert(2,index + 1);
896
sq_argassert(3,index + 2);
898
Get(TypeWrapper<P1>(),v,index + 0),
899
Get(TypeWrapper<P2>(),v,index + 1),
900
Get(TypeWrapper<P3>(),v,index + 2)
905
template<typename P1,typename P2,typename P3,typename P4>
906
static SQInteger Call(void (*func)(P1,P2,P3,P4),HSQUIRRELVM v,SQInteger index) {
907
sq_argassert(1,index + 0);
908
sq_argassert(2,index + 1);
909
sq_argassert(3,index + 2);
910
sq_argassert(4,index + 3);
912
Get(TypeWrapper<P1>(),v,index + 0),
913
Get(TypeWrapper<P2>(),v,index + 1),
914
Get(TypeWrapper<P3>(),v,index + 2),
915
Get(TypeWrapper<P4>(),v,index + 3)
920
template<typename P1,typename P2,typename P3,typename P4,typename P5>
921
static SQInteger Call(void (*func)(P1,P2,P3,P4,P5),HSQUIRRELVM v,SQInteger index) {
922
sq_argassert(1,index + 0);
923
sq_argassert(2,index + 1);
924
sq_argassert(3,index + 2);
925
sq_argassert(4,index + 3);
926
sq_argassert(5,index + 4);
928
Get(TypeWrapper<P1>(),v,index + 0),
929
Get(TypeWrapper<P2>(),v,index + 1),
930
Get(TypeWrapper<P3>(),v,index + 2),
931
Get(TypeWrapper<P4>(),v,index + 3),
932
Get(TypeWrapper<P5>(),v,index + 4)
937
template<typename P1,typename P2,typename P3,typename P4,typename P5,typename P6>
938
static SQInteger Call(void (*func)(P1,P2,P3,P4,P5,P6),HSQUIRRELVM v,SQInteger index) {
939
sq_argassert(1,index + 0);
940
sq_argassert(2,index + 1);
941
sq_argassert(3,index + 2);
942
sq_argassert(4,index + 3);
943
sq_argassert(5,index + 4);
944
sq_argassert(6,index + 5);
946
Get(TypeWrapper<P1>(),v,index + 0),
947
Get(TypeWrapper<P2>(),v,index + 1),
948
Get(TypeWrapper<P3>(),v,index + 2),
949
Get(TypeWrapper<P4>(),v,index + 3),
950
Get(TypeWrapper<P5>(),v,index + 4),
951
Get(TypeWrapper<P6>(),v,index + 5)
956
template<typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7>
957
static SQInteger Call(void (*func)(P1,P2,P3,P4,P5,P6,P7),HSQUIRRELVM v,SQInteger index) {
958
sq_argassert(1,index + 0);
959
sq_argassert(2,index + 1);
960
sq_argassert(3,index + 2);
961
sq_argassert(4,index + 3);
962
sq_argassert(5,index + 4);
963
sq_argassert(6,index + 5);
964
sq_argassert(7,index + 6);
966
Get(TypeWrapper<P1>(),v,index + 0),
967
Get(TypeWrapper<P2>(),v,index + 1),
968
Get(TypeWrapper<P3>(),v,index + 2),
969
Get(TypeWrapper<P4>(),v,index + 3),
970
Get(TypeWrapper<P5>(),v,index + 4),
971
Get(TypeWrapper<P6>(),v,index + 5),
972
Get(TypeWrapper<P7>(),v,index + 6)
977
// === Member function calls ===
979
template<typename Callee>
980
static SQInteger Call(Callee & callee,void (Callee::*func)(),HSQUIRRELVM,SQInteger /*index*/) {
985
template<typename Callee,typename P1>
986
static SQInteger Call(Callee & callee,void (Callee::*func)(P1),HSQUIRRELVM v,SQInteger index) {
987
sq_argassert(1,index + 0);
989
Get(TypeWrapper<P1>(),v,index + 0)
994
template<typename Callee,typename P1,typename P2>
995
static SQInteger Call(Callee & callee,void (Callee::*func)(P1,P2),HSQUIRRELVM v,SQInteger index) {
996
sq_argassert(1,index + 0);
997
sq_argassert(2,index + 1);
999
Get(TypeWrapper<P1>(),v,index + 0),
1000
Get(TypeWrapper<P2>(),v,index + 1)
1005
template<typename Callee,typename P1,typename P2,typename P3>
1006
static SQInteger Call(Callee & callee,void (Callee::*func)(P1,P2,P3),HSQUIRRELVM v,SQInteger index) {
1007
sq_argassert(1,index + 0);
1008
sq_argassert(2,index + 1);
1009
sq_argassert(3,index + 2);
1011
Get(TypeWrapper<P1>(),v,index + 0),
1012
Get(TypeWrapper<P2>(),v,index + 1),
1013
Get(TypeWrapper<P3>(),v,index + 2)
1018
template<typename Callee,typename P1,typename P2,typename P3,typename P4>
1019
static SQInteger Call(Callee & callee,void (Callee::*func)(P1,P2,P3,P4),HSQUIRRELVM v,SQInteger index) {
1020
sq_argassert(1,index + 0);
1021
sq_argassert(2,index + 1);
1022
sq_argassert(3,index + 2);
1023
sq_argassert(4,index + 3);
1025
Get(TypeWrapper<P1>(),v,index + 0),
1026
Get(TypeWrapper<P2>(),v,index + 1),
1027
Get(TypeWrapper<P3>(),v,index + 2),
1028
Get(TypeWrapper<P4>(),v,index + 3)
1033
template<typename Callee,typename P1,typename P2,typename P3,typename P4,typename P5>
1034
static SQInteger Call(Callee & callee,void (Callee::*func)(P1,P2,P3,P4,P5),HSQUIRRELVM v,SQInteger index) {
1035
sq_argassert(1,index + 0);
1036
sq_argassert(2,index + 1);
1037
sq_argassert(3,index + 2);
1038
sq_argassert(4,index + 3);
1039
sq_argassert(5,index + 4);
1041
Get(TypeWrapper<P1>(),v,index + 0),
1042
Get(TypeWrapper<P2>(),v,index + 1),
1043
Get(TypeWrapper<P3>(),v,index + 2),
1044
Get(TypeWrapper<P4>(),v,index + 3),
1045
Get(TypeWrapper<P5>(),v,index + 4)
1050
template<typename Callee,typename P1,typename P2,typename P3,typename P4,typename P5,typename P6>
1051
static SQInteger Call(Callee & callee,void (Callee::*func)(P1,P2,P3,P4,P5,P6),HSQUIRRELVM v,SQInteger index) {
1052
sq_argassert(1,index + 0);
1053
sq_argassert(2,index + 1);
1054
sq_argassert(3,index + 2);
1055
sq_argassert(4,index + 3);
1056
sq_argassert(5,index + 4);
1057
sq_argassert(6,index + 5);
1059
Get(TypeWrapper<P1>(),v,index + 0),
1060
Get(TypeWrapper<P2>(),v,index + 1),
1061
Get(TypeWrapper<P3>(),v,index + 2),
1062
Get(TypeWrapper<P4>(),v,index + 3),
1063
Get(TypeWrapper<P5>(),v,index + 4),
1064
Get(TypeWrapper<P6>(),v,index + 5)
1069
template<typename Callee,typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7>
1070
static SQInteger Call(Callee & callee,void (Callee::*func)(P1,P2,P3,P4,P5,P6,P7),HSQUIRRELVM v,SQInteger index) {
1071
sq_argassert(1,index + 0);
1072
sq_argassert(2,index + 1);
1073
sq_argassert(3,index + 2);
1074
sq_argassert(4,index + 3);
1075
sq_argassert(5,index + 4);
1076
sq_argassert(6,index + 5);
1077
sq_argassert(7,index + 6);
1079
Get(TypeWrapper<P1>(),v,index + 0),
1080
Get(TypeWrapper<P2>(),v,index + 1),
1081
Get(TypeWrapper<P3>(),v,index + 2),
1082
Get(TypeWrapper<P4>(),v,index + 3),
1083
Get(TypeWrapper<P5>(),v,index + 4),
1084
Get(TypeWrapper<P6>(),v,index + 5),
1085
Get(TypeWrapper<P7>(),v,index + 6)
1090
#ifdef SQPLUS_CONST_OPT
1091
#define SQPLUS_CALL_CONST_MFUNC_NORET
1092
#include "SqPlusConst.h"
1097
// === STANDARD Function return value specialized call handlers ===
1099
template<typename RT>
1100
SQInteger Call(RT (*func)(),HSQUIRRELVM v,SQInteger index) {
1101
return ReturnSpecialization<RT>::Call(func,v,index);
1104
template<typename RT,typename P1>
1105
SQInteger Call(RT (*func)(P1),HSQUIRRELVM v,SQInteger index) {
1106
return ReturnSpecialization<RT>::Call(func,v,index);
1109
template<typename RT,typename P1,typename P2>
1110
SQInteger Call(RT (*func)(P1,P2),HSQUIRRELVM v,SQInteger index) {
1111
return ReturnSpecialization<RT>::Call(func,v,index);
1114
template<typename RT,typename P1,typename P2,typename P3>
1115
SQInteger Call(RT (*func)(P1,P2,P3),HSQUIRRELVM v,SQInteger index) {
1116
return ReturnSpecialization<RT>::Call(func,v,index);
1119
template<typename RT,typename P1,typename P2,typename P3,typename P4>
1120
SQInteger Call(RT (*func)(P1,P2,P3,P4),HSQUIRRELVM v,SQInteger index) {
1121
return ReturnSpecialization<RT>::Call(func,v,index);
1124
template<typename RT,typename P1,typename P2,typename P3,typename P4,typename P5>
1125
SQInteger Call(RT (*func)(P1,P2,P3,P4,P5),HSQUIRRELVM v,SQInteger index) {
1126
return ReturnSpecialization<RT>::Call(func,v,index);
1129
template<typename RT,typename P1,typename P2,typename P3,typename P4,typename P5,typename P6>
1130
SQInteger Call(RT (*func)(P1,P2,P3,P4,P5,P6),HSQUIRRELVM v,SQInteger index) {
1131
return ReturnSpecialization<RT>::Call(func,v,index);
1134
template<typename RT,typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7>
1135
SQInteger Call(RT (*func)(P1,P2,P3,P4,P5,P6,P7),HSQUIRRELVM v,SQInteger index) {
1136
return ReturnSpecialization<RT>::Call(func,v,index);
1139
// === MEMBER Function return value specialized call handlers ===
1141
template<typename Callee,typename RT>
1142
SQInteger Call(Callee & callee, RT (Callee::*func)(),HSQUIRRELVM v,SQInteger index) {
1143
return ReturnSpecialization<RT>::Call(callee,func,v,index);
1146
template<typename Callee,typename RT,typename P1>
1147
SQInteger Call(Callee & callee,RT (Callee::*func)(P1),HSQUIRRELVM v,SQInteger index) {
1148
return ReturnSpecialization<RT>::Call(callee,func,v,index);
1151
template<typename Callee,typename RT,typename P1,typename P2>
1152
SQInteger Call(Callee & callee,RT (Callee::*func)(P1,P2),HSQUIRRELVM v,SQInteger index) {
1153
return ReturnSpecialization<RT>::Call(callee,func,v,index);
1156
template<typename Callee,typename RT,typename P1,typename P2,typename P3>
1157
SQInteger Call(Callee & callee,RT (Callee::*func)(P1,P2,P3),HSQUIRRELVM v,SQInteger index) {
1158
return ReturnSpecialization<RT>::Call(callee,func,v,index);
1161
template<typename Callee,typename RT,typename P1,typename P2,typename P3,typename P4>
1162
SQInteger Call(Callee & callee,RT (Callee::*func)(P1,P2,P3,P4),HSQUIRRELVM v,SQInteger index) {
1163
return ReturnSpecialization<RT>::Call(callee,func,v,index);
1166
template<typename Callee,typename RT,typename P1,typename P2,typename P3,typename P4,typename P5>
1167
SQInteger Call(Callee & callee,RT (Callee::*func)(P1,P2,P3,P4,P5),HSQUIRRELVM v,SQInteger index) {
1168
return ReturnSpecialization<RT>::Call(callee,func,v,index);
1171
template<typename Callee,typename RT,typename P1,typename P2,typename P3,typename P4,typename P5,typename P6>
1172
SQInteger Call(Callee & callee,RT (Callee::*func)(P1,P2,P3,P4,P5,P6),HSQUIRRELVM v,SQInteger index) {
1173
return ReturnSpecialization<RT>::Call(callee,func,v,index);
1176
template<typename Callee,typename RT,typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7>
1177
SQInteger Call(Callee & callee,RT (Callee::*func)(P1,P2,P3,P4,P5,P6,P7),HSQUIRRELVM v,SQInteger index) {
1178
return ReturnSpecialization<RT>::Call(callee,func,v,index);
1181
#ifdef SQPLUS_CONST_OPT
1182
#define SQPLUS_CALL_CONST_MFUNC_RET1
1183
#include "SqPlusConst.h"
1186
// === Direct Call Standard Function handler ===
1188
template<typename Func>
1189
struct DirectCallFunction {
1190
static inline SQInteger Dispatch(HSQUIRRELVM v) {
1192
SQInteger paramCount = sa.GetParamCount();
1193
Func * func = (Func *)sa.GetUserData(paramCount);
1194
return Call(*func,v,2);
1198
// === Direct Call Member Function handler ===
1200
template<typename Callee,typename Func>
1201
class DirectCallMemberFunction {
1203
static inline SQInteger Dispatch(HSQUIRRELVM v) {
1205
SQInteger paramCount = sa.GetParamCount();
1206
unsigned char * ud = (unsigned char *)sa.GetUserData(paramCount);
1207
// C::B patch: Handle invalid instance type here
1208
if (!*(Callee**)ud) {
1209
return sq_throwerror(v,sqT("Invalid Instance Type"));
1211
return Call(**(Callee**)ud,*(Func*)(ud + sizeof(Callee*)),v,2);
1215
// === Direct Call Instance Member Function handler ===
1217
#define SQ_CLASS_OBJECT_TABLE_NAME sqT("__ot")
1218
#define SQ_CLASS_HIER_ARRAY sqT("__ca")
1220
template<typename Callee,typename Func>
1221
class DirectCallInstanceMemberFunction {
1223
static inline SQInteger Dispatch(HSQUIRRELVM v) {
1225
Callee * instance = (Callee *)sa.GetInstanceUp(1,0);
1226
SQInteger paramCount = sa.GetParamCount();
1227
Func * func = (Func *)sa.GetUserData(paramCount);
1228
// C::B patch: Let the compiler search (comment out the whole block)
1229
//#ifdef SQ_USE_CLASS_INHERITANCE
1230
// SquirrelObject so(sa.GetObjectHandle(1)); // 'this'
1231
// SQUserPointer typetag; so.GetTypeTag(&typetag);
1232
// SQUserPointer calleeType = ClassType<Callee>::type();
1233
// if (typetag != calleeType) {
1234
// SquirrelObject typeTable = so.GetValue(SQ_CLASS_OBJECT_TABLE_NAME);
1235
// instance = (Callee *)typeTable.GetUserPointer(INT_T((size_t)ClassType<Callee>::type())); // <TODO> 64-bit compatible version.
1237
// return sq_throwerror(v,sqT("Invalid Instance Type"));
1241
// C::B patch: If not instance -> return Ok anyways
1244
return Call(*instance,*func,v,2);
1248
// === Direct Call Instance Member Function Variable Argument handler ===
1250
template<typename Callee>
1251
class DirectCallInstanceMemberFunctionVarArgs {
1253
typedef SQInteger (Callee::*FuncType)(HSQUIRRELVM);
1254
static inline SQInteger Dispatch(HSQUIRRELVM v) {
1256
Callee * instance = (Callee *)sa.GetInstanceUp(1,0);
1257
SQInteger paramCount = sa.GetParamCount();
1258
FuncType func = *(FuncType *)sa.GetUserData(paramCount);
1259
// C::B patch: Let the compiler search (comment out the whole block)
1260
//#ifdef SQ_USE_CLASS_INHERITANCE
1261
// SquirrelObject so(sa.GetObjectHandle(1)); // 'this'
1262
// SQUserPointer typetag; so.GetTypeTag(&typetag);
1263
// SQUserPointer calleeType = ClassType<Callee>::type();
1264
// if (typetag != calleeType) {
1265
// SquirrelObject typeTable = so.GetValue(SQ_CLASS_OBJECT_TABLE_NAME);
1266
// instance = (Callee *)typeTable.GetUserPointer(INT_T((size_t)ClassType<Callee>::type())); // <TODO> 64-bit compatible version.
1268
// return sq_throwerror(v,sqT("Invalid Instance Type"));
1272
sq_poptop(v); // Remove UserData from stack: so sa.GetParamCount() returns actual param count.
1273
// C::B patch: If not instance -> return Ok anyways
1276
return (instance->*func)(v);
1280
// Code fragment useful for debugging new implementations.
1282
HSQOBJECT ho = sa.GetObjectHandle(paramCount);
1283
SquirrelObject so(ho);
1284
SQObjectType sot = so.GetType();
1287
// === Standard function call ===
1289
template<typename Func>
1290
inline void sq_pushdirectclosure(HSQUIRRELVM v,Func func,SQUnsignedInteger nupvalues) {
1291
SQUserPointer up = sq_newuserdata(v,sizeof(func)); // Also pushed on stack.
1292
memcpy(up,&func,sizeof(func));
1293
sq_newclosure(v,DirectCallFunction<Func>::Dispatch,nupvalues+1);
1294
} // sq_pushdirectclosure
1296
// === Fixed Class pointer call (always calls with object pointer that was registered) ===
1298
template<typename Callee,typename Func>
1299
inline void sq_pushdirectclosure(HSQUIRRELVM v,const Callee & callee,Func func,SQUnsignedInteger nupvalues) {
1300
unsigned char * up = (unsigned char *)sq_newuserdata(v,sizeof(Callee*)+sizeof(func)); // Also pushed on stack.
1301
const SQUserPointer pCallee = (SQUserPointer)&callee;
1302
memcpy(up,&pCallee,sizeof(Callee*));
1303
memcpy(up + sizeof(Callee*),&func,sizeof(func));
1304
sq_newclosure(v,DirectCallMemberFunction<Callee,Func>::Dispatch,nupvalues+1);
1305
} // sq_pushdirectclosure
1307
// === Class Instance call: class pointer retrieved from script class instance ===
1309
template<typename Callee,typename Func>
1310
inline void sq_pushdirectinstanceclosure(HSQUIRRELVM v,const Callee & /*callee*/,Func func,SQUnsignedInteger nupvalues) {
1311
unsigned char * up = (unsigned char *)sq_newuserdata(v,sizeof(func)); // Also pushed on stack.
1312
memcpy(up,&func,sizeof(func));
1313
sq_newclosure(v,DirectCallInstanceMemberFunction<Callee,Func>::Dispatch,nupvalues+1);
1314
} // sq_pushdirectinstanceclosure
1316
// === Class Instance call: class pointer retrieved from script class instance (variable arguments) ===
1318
template<typename Callee>
1319
inline void sq_pushdirectinstanceclosurevarargs(HSQUIRRELVM v,const Callee & callee,SQInteger (Callee::*func)(HSQUIRRELVM),SQUnsignedInteger nupvalues) {
1320
unsigned char * up = (unsigned char *)sq_newuserdata(v,sizeof(func)); // Also pushed on stack.
1321
memcpy(up,&func,sizeof(func));
1322
sq_newclosure(v,DirectCallInstanceMemberFunctionVarArgs<Callee>::Dispatch,nupvalues+1);
1323
} // sq_pushdirectinstanceclosurevarargs
1325
// === Register a STANDARD function (table or class on stack) ===
1327
template<typename Func>
1328
inline void Register(HSQUIRRELVM v,Func func,const SQChar * name) {
1329
sq_pushstring(v,name,-1);
1330
sq_pushdirectclosure(v,func,0);
1331
sq_createslot(v,-3); // Stack is restored after this call (same state as before Register() call).
1334
// === Register a MEMBER function (table or class on stack) ===
1336
template<typename Callee,typename Func>
1337
inline void Register(HSQUIRRELVM v,Callee & callee,Func func,const SQChar * name) {
1338
sq_pushstring(v,name,-1);
1339
sq_pushdirectclosure(v,callee,func,0);
1340
sq_createslot(v,-3); // Stack is restored after this call (same state as before Register() call).
1343
// === Register a STANDARD global function (root table) ===
1345
template<typename Func>
1346
inline void RegisterGlobal(HSQUIRRELVM v,Func func,const SQChar * name) {
1347
sq_pushroottable(v);
1348
Register(v,func,name);
1349
sq_poptop(v); // Remove root table.
1352
template<typename Func>
1353
inline void RegisterGlobal(Func func,const SQChar * name) {
1354
RegisterGlobal(SquirrelVM::GetVMPtr(),func,name);
1357
// === Register a MEMBER global function (root table) ===
1359
template<typename Callee,typename Func>
1360
inline void RegisterGlobal(HSQUIRRELVM v,Callee & callee,Func func,const SQChar * name) {
1361
sq_pushroottable(v);
1362
Register(v,callee,func,name);
1363
sq_poptop(v); // Remove root table.
1366
template<typename Callee,typename Func>
1367
inline void RegisterGlobal(Callee & callee,Func func,const SQChar * name) {
1368
RegisterGlobal(SquirrelVM::GetVMPtr(),callee,func,name);
1371
// === Register a STANDARD function (hso is table or class) ===
1373
template<typename Func>
1374
inline void Register(HSQUIRRELVM v,HSQOBJECT hso,Func func,const SQChar * name) {
1375
sq_pushobject(v,hso);
1376
Register(v,func,name);
1377
sq_poptop(v); // Remove hso.
1380
// === Register a MEMBER function (hso is table or class) ===
1381
// === Fixed Class pointer call (always calls with object pointer that was registered) ===
1383
template<typename Callee,typename Func>
1384
inline void Register(HSQUIRRELVM v,HSQOBJECT hso,Callee & callee,Func func,const SQChar * name) {
1385
sq_pushobject(v,hso);
1386
Register(v,callee,func,name);
1387
sq_poptop(v); // Remove hso.
1390
// === Register an INSTANCE MEMBER function ===
1391
// === Class Instance call: class pointer retrieved from script class instance ===
1393
template<typename Callee,typename Func>
1394
inline void RegisterInstance(HSQUIRRELVM v,HSQOBJECT hclass,Callee & callee,Func func,const SQChar * name) {
1395
sq_pushobject(v,hclass);
1396
sq_pushstring(v,name,-1);
1397
sq_pushdirectinstanceclosure(v,callee,func,0);
1398
sq_createslot(v,-3);
1399
sq_poptop(v); // Remove hclass.
1400
} // RegisterInstance
1404
#pragma warning(disable : 4995) // Deprecated _snprintf
1407
// === Register an INSTANCE MEMBER function Variable Arguments ===
1408
// typeMask: "*" means don't check parameters, typeMask=0 means function takes no arguments (and is type checked for that case).
1409
// All the other Squirrel type-masks are passed normally.
1411
template<typename Callee>
1412
inline void RegisterInstanceVarArgs(HSQUIRRELVM v,HSQOBJECT hclass,Callee & callee,SQInteger (Callee::*func)(HSQUIRRELVM),const SQChar * name,const SQChar * typeMask=sqT("*")) {
1413
sq_pushobject(v,hclass);
1414
sq_pushstring(v,name,-1);
1415
sq_pushdirectinstanceclosurevarargs(v,callee,func,0);
1418
SQInteger numParams = SQ_MATCHTYPEMASKSTRING;
1420
if (typeMask[0] == '*') {
1421
ptm = 0; // Variable args: don't check parameters.
1422
// numParams = 0; // Clear SQ_MATCHTYPEMASKSTRING (does not mean match 0 params. See sq_setparamscheck()).
1424
if (SCSNPRINTF(tm,sizeof(tm),sqT("x%s"),typeMask) < 0) { // Must be an instance.
1425
throw SquirrelError(sqT("RegisterInstanceVarArgs: typeMask string too long."));
1428
} else { // <TODO> Need to check object type on stack: table, class, instance, etc.
1429
// _snprintf(tm,sizeof(tm),"x"); // instance.
1433
if (ptm) { // If ptm == 0, don't check type.
1434
sq_setparamscheck(v,numParams,ptm); // Determine arg count from type string.
1437
sq_setnativeclosurename(v,-1,name); // For debugging only.
1439
sq_createslot(v,-3);
1440
sq_poptop(v); // Remove hclass.
1441
} // RegisterInstanceVarArgs
1444
#pragma warning(default : 4995)
1447
// === Call Squirrel Functions from C/C++ ===
1448
// No type checking is performed for Squirrel functions as Squirrel types are dynamic:
1449
// Incoming types are passed unchanged to Squirrel functions. The parameter count is checked: an exception is thrown if mismatched.
1450
// Return values must match the RT template argument type, else an exception can be thrown on return.
1452
template<typename RT>
1453
struct SquirrelFunction {
1455
SquirrelObject object; // Table or class.
1456
SquirrelObject func;
1457
SquirrelFunction() : v(0) {}
1458
SquirrelFunction(HSQUIRRELVM _v,const SquirrelObject & _object,const SquirrelObject & _func) : v(_v), object(_object), func(_func) {}
1459
SquirrelFunction(const SquirrelObject & _object,const SquirrelObject & _func) : v(SquirrelVM::GetVMPtr()), object(_object), func(_func) {}
1460
SquirrelFunction(const SquirrelObject & _object,const SQChar * name) {
1461
v = SquirrelVM::GetVMPtr();
1463
func = object.GetValue(name);
1465
SquirrelFunction(const SQChar * name) {
1466
v = SquirrelVM::GetVMPtr();
1467
object = SquirrelVM::GetRootTable();
1468
func = object.GetValue(name);
1471
// Release references and reset internal objects to null.
1477
#define SQPLUS_CHECK_FNCALL(res) if (!SQ_SUCCEEDED(res)) throw SquirrelError(sqT("SquirrelFunction<> call failed"))
1479
RT operator()(void) {
1480
sq_pushobject(v,func.GetObjectHandle());
1481
sq_pushobject(v,object.GetObjectHandle());
1482
SQPLUS_CHECK_FNCALL(sq_call(v,1,SQTrue,SQ_CALL_RAISE_ERROR));
1483
return GetRet(TypeWrapper<RT>(),v,-1);
1486
template<typename P1>
1487
RT operator()(P1 p1) {
1488
sq_pushobject(v,func.GetObjectHandle());
1489
sq_pushobject(v,object.GetObjectHandle());
1491
SQPLUS_CHECK_FNCALL(sq_call(v,2,SQTrue,SQ_CALL_RAISE_ERROR));
1492
return GetRet(TypeWrapper<RT>(),v,-1);
1495
template<typename P1,typename P2>
1496
RT operator()(P1 p1,P2 p2) {
1497
sq_pushobject(v,func.GetObjectHandle());
1498
sq_pushobject(v,object.GetObjectHandle());
1501
SQPLUS_CHECK_FNCALL(sq_call(v,3,SQTrue,SQ_CALL_RAISE_ERROR));
1502
return GetRet(TypeWrapper<RT>(),v,-1);
1505
template<typename P1,typename P2,typename P3>
1506
RT operator()(P1 p1,P2 p2,P3 p3) {
1507
sq_pushobject(v,func.GetObjectHandle());
1508
sq_pushobject(v,object.GetObjectHandle());
1512
SQPLUS_CHECK_FNCALL(sq_call(v,4,SQTrue,SQ_CALL_RAISE_ERROR));
1513
return GetRet(TypeWrapper<RT>(),v,-1);
1516
template<typename P1,typename P2,typename P3,typename P4>
1517
RT operator()(P1 p1,P2 p2,P3 p3,P4 p4) {
1518
sq_pushobject(v,func.GetObjectHandle());
1519
sq_pushobject(v,object.GetObjectHandle());
1524
SQPLUS_CHECK_FNCALL(sq_call(v,5,SQTrue,SQ_CALL_RAISE_ERROR));
1525
return GetRet(TypeWrapper<RT>(),v,-1);
1528
template<typename P1,typename P2,typename P3,typename P4,typename P5>
1529
RT operator()(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5) {
1530
sq_pushobject(v,func.GetObjectHandle());
1531
sq_pushobject(v,object.GetObjectHandle());
1537
SQPLUS_CHECK_FNCALL(sq_call(v,6,SQTrue,SQ_CALL_RAISE_ERROR));
1538
return GetRet(TypeWrapper<RT>(),v,-1);
1541
template<typename P1,typename P2,typename P3,typename P4,typename P5,typename P6>
1542
RT operator()(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5,P6 p6) {
1543
sq_pushobject(v,func.GetObjectHandle());
1544
sq_pushobject(v,object.GetObjectHandle());
1551
SQPLUS_CHECK_FNCALL(sq_call(v,7,SQTrue,SQ_CALL_RAISE_ERROR));
1552
return GetRet(TypeWrapper<RT>(),v,-1);
1555
template<typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7>
1556
RT operator()(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5,P6 p6,P7 p7) {
1557
sq_pushobject(v,func.GetObjectHandle());
1558
sq_pushobject(v,object.GetObjectHandle());
1566
SQPLUS_CHECK_FNCALL(sq_call(v,8,SQTrue,SQ_CALL_RAISE_ERROR));
1567
return GetRet(TypeWrapper<RT>(),v,-1);
1572
// === Class/Struct registration ===
1574
#define SQ_DELETE_CLASS(CLASSTYPE) if (up) { CLASSTYPE * self = (CLASSTYPE *)up; delete self;} return 0
1575
#define SQ_DECLARE_RELEASE(CLASSTYPE) \
1576
static SQInteger release(SQUserPointer up, SQInteger /*size*/) { \
1577
SQ_DELETE_CLASS(CLASSTYPE); \
1580
template<typename T>
1581
struct ReleaseClassPtrPtr {
1582
static SQInteger release(SQUserPointer up,SQInteger size) {
1584
T ** self = (T **)up;
1591
template<typename T>
1592
struct ReleaseClassPtr {
1593
static SQInteger release(SQUserPointer up,SQInteger size) {
1602
BOOL_T CreateClass(HSQUIRRELVM v,SquirrelObject & newClass,SQUserPointer classType,const SQChar * name,const SQChar * baseName=0);
1604
#define SQ_ANCESTOR_CLASS_INDEX sqT("__ci")
1606
// Call PostConstruct() at the end of custom constructors.
1607
template<typename T>
1608
inline SQInteger PostConstruct(HSQUIRRELVM v,T * newClass,SQRELEASEHOOK hook) {
1609
#ifdef SQ_USE_CLASS_INHERITANCE
1611
HSQOBJECT ho = sa.GetObjectHandle(1); // OT_INSTANCE
1612
SquirrelObject instance(ho);
1613
INT_T classIndex = instance.GetValue(SQ_ANCESTOR_CLASS_INDEX).ToInteger();
1614
if (classIndex == -1) { // Is this the most-derived C/C++ class? If so, create all ancestors (if present).
1616
SquirrelObject newObjectTable = SquirrelVM::CreateTable(); // 11/2/05: Create a new table for this instance.
1617
newObjectTable.SetUserPointer(INT_T((size_t)ClassType<T>::type()),newClass); // <TODO> 64-bit compatible version.
1618
instance.SetValue(SQ_CLASS_OBJECT_TABLE_NAME,newObjectTable);
1620
SquirrelObject classHierArray = instance.GetValue(SQ_CLASS_HIER_ARRAY);
1621
INT_T count = classHierArray.Len();
1622
if (count > 1) { // This will be true when more than one C/C++ class is in the hierarchy.
1623
--count; // Skip the most-derived class.
1624
for (INT_T i=0; i < count; i++) {
1625
#ifdef CPP_STYLE_INHERITANCE // Kamaitati's changes for C++ inheritance support. jcs 5/28/06
1626
SquirrelObject so = classHierArray.GetValue(i);
1627
sq_pushobject(v,so.GetObjectHandle());
1628
SQUserPointer typeTag;
1629
sq_gettypetag(v,-1,&typeTag);
1630
newObjectTable.SetUserPointer(INT_T(size_t(typeTag)),newClass);
1633
instance.SetValue(SQ_ANCESTOR_CLASS_INDEX,i); // Store ancestor class index for recursive constructor calls to come.
1634
INT_T top = sq_gettop(v);
1635
SquirrelObject so = classHierArray.GetValue(i); // Need to create UserData struct: store pointer to class, set release hook.
1636
SquirrelObject func = so.GetValue(sqT("constructor"));
1637
sq_pushobject(v,func.GetObjectHandle());
1638
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).
1639
sq_call(v,1,SQFalse,SQ_CALL_RAISE_ERROR); // Call constructor: no arguments are passed other than the 'instance'.
1643
instance.SetValue(SQ_ANCESTOR_CLASS_INDEX,SquirrelObject()); // Store an OT_NULL object to free SQ_ANCESTOR_CLASS_INDEX var.
1645
} else { // Ancestor: Construct class and set release hook.
1647
SquirrelObject objectTable = instance.GetValue(SQ_CLASS_OBJECT_TABLE_NAME); // 11/2/05: Get the existing object table.
1648
objectTable.SetUserPointer(INT_T((size_t)ClassType<T>::type()),newClass); // <TODO> 64-bit compatible version.
1650
INT_T top = sq_gettop(v);
1651
T ** ud = (T **)sq_newuserdata(v,sizeof(T *)); // Create UserData and push onto stack.
1653
// C::B patch: Disable releasing of objects (due to private/protected dtors) (Note: This is evil, but no other possibility found.)
1654
// sq_setreleasehook(v,-1,ReleaseClassPtrPtr<T>::release); // Set release hook for UserData on stack.
1655
SquirrelObject userData;
1656
userData.AttachToStackObject(-1);
1657
SquirrelObject classHierArray = instance.GetValue(SQ_CLASS_HIER_ARRAY);
1658
classHierArray.SetValue(classIndex,userData); // Replace the class entry with UserData: will be freed during most-derived class destruction.
1663
sq_setinstanceup(v,1,newClass);
1664
sq_setreleasehook(v,1,hook);
1668
template<typename T>
1669
struct ConstructReleaseClass {
1670
static SQInteger construct(HSQUIRRELVM v) {
1671
return PostConstruct<T>(v,new T(),release);
1673
// C::B patch: Add empty constructor
1674
static SQInteger no_construct(HSQUIRRELVM v) {
1675
return PostConstruct<T>(v,0,0);
1677
SQ_DECLARE_RELEASE(T)
1680
template<typename T>
1681
inline SquirrelObject RegisterClassType(HSQUIRRELVM v,const SQChar * scriptClassName,const SQChar * baseScriptClassName=0) {
1682
SQInteger top = sq_gettop(v);
1683
SquirrelObject newClass;
1684
if (CreateClass(v,newClass,(SQUserPointer)ClassType<T>::type(),scriptClassName,baseScriptClassName)) {
1685
SquirrelVM::CreateFunction(newClass,&ConstructReleaseClass<T>::no_construct,sqT("constructor"));
1686
#ifdef SQ_USE_CLASS_INHERITANCE
1687
// <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.
1688
if (!newClass.Exists(SQ_CLASS_OBJECT_TABLE_NAME)) { // Will always get table from most-derived registered class.
1689
SquirrelObject objectTable = SquirrelVM::CreateTable();
1690
newClass.SetValue(SQ_CLASS_OBJECT_TABLE_NAME,objectTable); // Constructors must add their 'this' pointer indexed by type to this table. See PostConstruct() above.
1691
// 11/2/05: This table will behave as a static global for each instance unless overwritten during construction (see PostConstruct() above).
1693
SquirrelObject classHierArray;
1694
if (!newClass.Exists(SQ_CLASS_HIER_ARRAY)) { // Will always get table from most-derived registered class.
1695
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.
1696
newClass.SetValue(SQ_CLASS_HIER_ARRAY,classHierArray);
1698
classHierArray = newClass.GetValue(SQ_CLASS_HIER_ARRAY);
1700
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.
1701
// C::B patch for 64bit builds
1702
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.
1707
} // RegisterClassType
1709
// === Define and register a C++ class and its members for use with Squirrel ===
1710
// Constructors+destructors are automatically created. Custom constructors must use the
1711
// standard SQFUNCTION signature if variable argument types are required (overloads).
1712
// See testSqPlus2.cpp for examples.
1714
template<typename TClassType>
1717
const SQChar * name;
1718
const SQChar * base;
1719
SquirrelObject newClass;
1721
#ifdef SQ_USE_CLASS_INHERITANCE
1722
// Optional base arg is the name of a base class to inherit from (must already be defined in the Squirrel VM).
1723
SQClassDef(HSQUIRRELVM _v,const SQChar * _name,const SQChar * _base=0) : v(_v), name(_name), base(_base) {
1724
newClass = RegisterClassType<TClassType>(v,name,base);
1726
// Optional base arg is the name of a base class to inherit from (must already be defined in the Squirrel VM).
1727
SQClassDef(const SQChar * _name,const SQChar * _base=0) : name(_name), base(_base) {
1728
v = SquirrelVM::GetVMPtr();
1729
newClass = RegisterClassType<TClassType>(v,name,base);
1732
SQClassDef(HSQUIRRELVM _v,const SQChar * _name) : v(_v), name(_name) {
1733
newClass = RegisterClassType<TClassType>(v,name);
1736
SQClassDef(const SQChar * _name) : name(_name) {
1737
v = SquirrelVM::GetVMPtr();
1738
newClass = RegisterClassType<TClassType>(v,name);
1742
// C::B patch: Add empty constructor
1743
SQClassDef & emptyCtor() {
1744
SquirrelVM::CreateFunction(newClass,&ConstructReleaseClass<TClassType>::construct,sqT("constructor"));
1748
// Register a member function.
1749
template<typename Func>
1750
SQClassDef & func(Func pfunc,const SQChar * name_) {
1751
RegisterInstance(v,newClass.GetObjectHandle(),*(TClassType *)0,pfunc,name_);
1755
// Register a variable-argument member function (supports variable+multiple return values).
1756
// typeMask: "*" means don't check parameters, typeMask=0 means function takes no arguments (and is type checked for that case).
1757
// All the other Squirrel type-masks are passed normally.
1758
template<typename Func>
1759
SQClassDef & funcVarArgs(Func pfunc,const SQChar * name_,const SQChar * typeMask=sqT("*")) {
1760
RegisterInstanceVarArgs(v,newClass.GetObjectHandle(),*(TClassType *)0,pfunc,name_,typeMask);
1764
// === BEGIN static-member+global function registration ===
1766
// === This version is for static member functions only, such as custom constructors where 'this' is not yet valid ===
1767
// typeMask: "*" means don't check parameters, typeMask=0 means function takes no arguments (and is type checked for that case).
1768
// All the other Squirrel type-masks are passed normally.
1770
template<typename Func>
1771
SQClassDef & staticFuncVarArgs(Func pfunc,const SQChar * name_,const SQChar * typeMask=sqT("*")) {
1772
SquirrelVM::PushObject(newClass);
1773
SquirrelVM::CreateFunction(pfunc,name_,typeMask);
1776
} // staticFuncVarArgs
1778
// Register a standard global function (effectively embedding a global function in TClassType's script namespace: does not need or use a 'this' pointer).
1779
template<typename Func>
1780
SQClassDef & staticFunc(Func pfunc,const SQChar * name_) {
1781
Register(v,newClass.GetObjectHandle(),pfunc,name_);
1785
// 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).
1786
template<typename Callee,typename Func>
1787
SQClassDef & staticFunc(Callee & callee,Func pfunc,const SQChar * name_) {
1788
Register(v,newClass.GetObjectHandle(),callee,pfunc,name_);
1792
// === END static+global function registration ===
1794
// Register a member variable.
1795
template<typename VarType>
1796
SQClassDef & var(VarType TClassType::* pvar,const SQChar * name_,VarAccessType access=VAR_ACCESS_READ_WRITE) {
1798
VarType TClassType::* var;
1799
} cv; // Cast Variable helper.
1801
RegisterInstanceVariable(newClass,ClassType<TClassType>::type(),*(VarType **)&cv,name_,access);
1805
// Register a member variable as a UserPointer (read only).
1806
template<typename VarType>
1807
SQClassDef & varAsUserPointer(VarType TClassType::* pvar,const SQChar * name_) {
1809
VarType TClassType::* var;
1810
} cv; // Cast Variable helper.
1812
RegisterInstanceVariable(newClass,ClassType<TClassType>::type(),*(SQAnything **)&cv,name_,VAR_ACCESS_READ_ONLY);
1814
} // varAsUserPointer
1816
template<typename VarType>
1817
SQClassDef & staticVar(VarType * pvar,const SQChar * name_,VarAccessType access=VAR_ACCESS_READ_WRITE) {
1820
} cv; // Cast Variable helper.
1822
RegisterInstanceVariable(newClass,ClassType<TClassType>::type(),*(VarType **)&cv,name_,VarAccessType(access|VAR_ACCESS_STATIC));
1826
#ifdef SQPLUS_CONST_OPT
1827
#define SQ_REG_CONST_STATIC_VAR
1828
#include "SqPlusConst.h"
1831
// Register a constant (read-only in script, passed by value (only INT_T, FLOAT_T, or BOOL_T types)).
1832
template<typename ConstantType>
1833
SQClassDef & constant(ConstantType constant_,const SQChar * name_) {
1834
RegisterInstanceConstant(newClass,ClassType<TClassType>::type(),constant_,name_);
1838
// Register an enum as an integer (read-only in script).
1839
SQClassDef & enumInt(SQInteger constant_,const SQChar * name_) {
1840
RegisterInstanceConstant(newClass,ClassType<TClassType>::type(),constant_,name_);
1846
// === BEGIN Function Call Handlers ===
1848
inline void Push(HSQUIRRELVM v,char value) { sq_pushinteger(v,value); }
1849
inline void Push(HSQUIRRELVM v,unsigned char value) { sq_pushinteger(v,value); }
1850
inline void Push(HSQUIRRELVM v,short value) { sq_pushinteger(v,value); }
1851
inline void Push(HSQUIRRELVM v,unsigned short value) { sq_pushinteger(v,value); }
1852
inline void Push(HSQUIRRELVM v,int value) { sq_pushinteger(v,value); }
1853
inline void Push(HSQUIRRELVM v,unsigned int value) { sq_pushinteger(v,value); }
1854
inline void Push(HSQUIRRELVM v,long value) { sq_pushinteger(v,value); }
1855
inline void Push(HSQUIRRELVM v,long long value) { sq_pushinteger(v,value); }
1856
inline void Push(HSQUIRRELVM v,unsigned long value) { sq_pushinteger(v,value); }
1857
inline void Push(HSQUIRRELVM v,unsigned long long value) { sq_pushinteger(v,value); }
1858
inline void Push(HSQUIRRELVM v,double value) { sq_pushfloat(v,(FLOAT_T)value); }
1859
inline void Push(HSQUIRRELVM v,float value) { sq_pushfloat(v,(FLOAT_T)value); }
1860
inline void Push(HSQUIRRELVM v,const SQChar * value) { sq_pushstring(v,value,-1); }
1861
inline void Push(HSQUIRRELVM v,const SquirrelNull &) { sq_pushnull(v); }
1862
inline void Push(HSQUIRRELVM v,SQFUNCTION value) { sq_pushuserpointer(v,(void*)value); }
1863
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.
1864
inline void Push(HSQUIRRELVM v,SquirrelObject & so) { sq_pushobject(v,so.GetObjectHandle()); }
1867
#define USE_ARGUMENT_DEPENDANT_OVERLOADS
1868
#ifdef USE_ARGUMENT_DEPENDANT_OVERLOADS
1870
#pragma warning (disable:4675) // Disable warning: "resolved overload was found by argument-dependent lookup" when class/struct pointers are used as function arguments.
1872
// === BEGIN Argument Dependent Overloads ===
1873
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.
1874
inline void Push(HSQUIRRELVM v,const void * value) { sq_pushuserpointer(v,(void*)value); } // Pass SQAnythingPtr instead of void * " "
1875
inline void Push(HSQUIRRELVM v,const SQUserPointer & value) { sq_pushuserpointer(v,(void*)value); }
1876
// === END Argument Dependent Overloads ===
1879
#define SQPLUS_CHECK_GET(res) if (!SQ_SUCCEEDED(res)) throw SquirrelError(sqT("sq_get*() failed (type error)"))
1881
inline bool Match(TypeWrapper<bool>,HSQUIRRELVM v,SQInteger idx) { return sq_gettype(v,idx) == OT_BOOL; }
1882
inline bool Match(TypeWrapper<char>,HSQUIRRELVM v,SQInteger idx) { return sq_gettype(v,idx) == OT_INTEGER; }
1883
inline bool Match(TypeWrapper<unsigned char>,HSQUIRRELVM v, SQInteger idx) { return sq_gettype(v,idx) == OT_INTEGER; }
1884
inline bool Match(TypeWrapper<short>,HSQUIRRELVM v,SQInteger idx) { return sq_gettype(v,idx) == OT_INTEGER; }
1885
inline bool Match(TypeWrapper<unsigned short>,HSQUIRRELVM v,SQInteger idx) { return sq_gettype(v,idx) == OT_INTEGER; }
1886
inline bool Match(TypeWrapper<int>,HSQUIRRELVM v,SQInteger idx) { return sq_gettype(v,idx) == OT_INTEGER; }
1887
inline bool Match(TypeWrapper<unsigned int>,HSQUIRRELVM v,SQInteger idx) { return sq_gettype(v,idx) == OT_INTEGER; }
1888
inline bool Match(TypeWrapper<long>,HSQUIRRELVM v,SQInteger idx) { return sq_gettype(v,idx) == OT_INTEGER; }
1889
inline bool Match(TypeWrapper<long long>,HSQUIRRELVM v,SQInteger idx) { return sq_gettype(v,idx) == OT_INTEGER; }
1890
inline bool Match(TypeWrapper<unsigned long>,HSQUIRRELVM v,SQInteger idx) { return sq_gettype(v,idx) == OT_INTEGER; }
1891
inline bool Match(TypeWrapper<unsigned long long>,HSQUIRRELVM v,SQInteger idx) { return sq_gettype(v,idx) == OT_INTEGER; }
1892
inline bool Match(TypeWrapper<float>,HSQUIRRELVM v,SQInteger idx) { SQInteger type = sq_gettype(v,idx); return type == OT_FLOAT; }
1893
inline bool Match(TypeWrapper<double>,HSQUIRRELVM v,SQInteger idx) { SQInteger type = sq_gettype(v,idx); return type == OT_FLOAT; }
1894
inline bool Match(TypeWrapper<const SQChar *>,HSQUIRRELVM v,SQInteger idx) { return sq_gettype(v,idx) == OT_STRING; }
1895
inline bool Match(TypeWrapper<HSQUIRRELVM>,HSQUIRRELVM /*v*/,SQInteger /*idx*/){ return true; } // See Get() for HSQUIRRELVM below (v is always present).
1896
inline bool Match(TypeWrapper<void*>,HSQUIRRELVM v,SQInteger idx) { return sq_gettype(v,idx) == OT_USERPOINTER; }
1897
inline bool Match(TypeWrapper<SquirrelObject>,HSQUIRRELVM /*v*/,SQInteger /*idx*/) { return true; } // See sq_getstackobj(): always returns true.
1899
inline void Get(TypeWrapper<void>,HSQUIRRELVM /*v*/,int) { ; }
1900
inline bool Get(TypeWrapper<bool>,HSQUIRRELVM v,SQInteger idx) { SQBool b; SQPLUS_CHECK_GET(sq_getbool(v,idx,&b)); return b != 0; }
1901
inline char Get(TypeWrapper<char>,HSQUIRRELVM v,SQInteger idx) { INT_T i; SQPLUS_CHECK_GET(sq_getinteger(v,idx,&i)); return static_cast<char>(i); }
1902
inline unsigned char Get(TypeWrapper<unsigned char>,HSQUIRRELVM v,SQInteger idx) { INT_T i; SQPLUS_CHECK_GET(sq_getinteger(v,idx,&i)); return static_cast<unsigned char>(i); }
1903
inline short Get(TypeWrapper<short>,HSQUIRRELVM v,SQInteger idx) { INT_T i; SQPLUS_CHECK_GET(sq_getinteger(v,idx,&i)); return static_cast<short>(i); }
1904
inline unsigned short Get(TypeWrapper<unsigned short>,HSQUIRRELVM v,SQInteger idx) { INT_T i; SQPLUS_CHECK_GET(sq_getinteger(v,idx,&i)); return static_cast<unsigned short>(i); }
1905
inline int Get(TypeWrapper<int>,HSQUIRRELVM v,SQInteger idx) { INT_T i; SQPLUS_CHECK_GET(sq_getinteger(v,idx,&i)); return i; }
1906
inline unsigned int Get(TypeWrapper<unsigned int>,HSQUIRRELVM v,SQInteger idx) { INT_T i; SQPLUS_CHECK_GET(sq_getinteger(v,idx,&i)); return static_cast<unsigned int>(i); }
1907
inline long Get(TypeWrapper<long>,HSQUIRRELVM v,SQInteger idx) { INT_T i; SQPLUS_CHECK_GET(sq_getinteger(v,idx,&i)); return static_cast<long>(i); }
1908
inline long long Get(TypeWrapper<long long>,HSQUIRRELVM v,SQInteger idx) { INT_T i; SQPLUS_CHECK_GET(sq_getinteger(v,idx,&i)); return static_cast<long long>(i); }
1909
inline unsigned long Get(TypeWrapper<unsigned long>,HSQUIRRELVM v,SQInteger idx) { INT_T i; SQPLUS_CHECK_GET(sq_getinteger(v,idx,&i)); return static_cast<unsigned long>(i); }
1910
inline unsigned long long Get(TypeWrapper<unsigned long long>, HSQUIRRELVM v,SQInteger idx) { INT_T i; SQPLUS_CHECK_GET(sq_getinteger(v,idx,&i)); return static_cast<unsigned long long>(i); }
1911
inline float Get(TypeWrapper<float>,HSQUIRRELVM v,SQInteger idx) { FLOAT_T f; SQPLUS_CHECK_GET(sq_getfloat(v,idx,&f)); return f; }
1912
inline double Get(TypeWrapper<double>,HSQUIRRELVM v,SQInteger idx) { FLOAT_T f; SQPLUS_CHECK_GET(sq_getfloat(v,idx,&f)); return static_cast<double>(f); }
1913
inline const SQChar * Get(TypeWrapper<const SQChar *>,HSQUIRRELVM v,SQInteger idx) { const SQChar * s; SQPLUS_CHECK_GET(sq_getstring(v,idx,&s)); return s; }
1914
inline SquirrelNull Get(TypeWrapper<SquirrelNull>,HSQUIRRELVM v,SQInteger idx) { (void)v, (void)idx; return SquirrelNull(); }
1915
inline void * Get(TypeWrapper<void *>,HSQUIRRELVM v,SQInteger idx) { SQUserPointer p; SQPLUS_CHECK_GET(sq_getuserpointer(v,idx,&p)); return p; }
1916
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.
1917
inline SquirrelObject Get(TypeWrapper<SquirrelObject>,HSQUIRRELVM v,SQInteger idx) { HSQOBJECT o; SQPLUS_CHECK_GET(sq_getstackobj(v,idx,&o)); return SquirrelObject(o); }
1919
#ifdef SQPLUS_SUPPORT_STD_STRING
1920
inline void Push(HSQUIRRELVM v,const std::string& value) { sq_pushstring(v,value.c_str(),-1); }
1921
inline bool Match(TypeWrapper<const std::string&>, HSQUIRRELVM v, SQInteger idx) { return sq_gettype(v,idx) == OT_STRING; }
1922
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); }
1925
// Added jflanglois suggestion, 8/20/06. jcs
1926
#ifdef SQPLUS_SUPPORT_SQ_STD_STRING
1927
typedef std::basic_string<SQChar> sq_std_string;
1928
inline void Push(HSQUIRRELVM v,const sq_std_string & value) { sq_pushstring(v,value.c_str(),-1); }
1929
inline bool Match(TypeWrapper<const sq_std_string &>, HSQUIRRELVM v, SQInteger idx) { return sq_gettype(v,idx) == OT_STRING; }
1930
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); }
1933
// GetRet() restores the stack for SquirrelFunction<>() calls.
1934
template<typename RT>
1935
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.
1937
// Specialization to support void return type.
1938
inline void GetRet(TypeWrapper<void>,HSQUIRRELVM v,SQInteger /*idx*/) { sq_pop(v,2); }
1940
// === END Function Call Handlers ===
1942
// === Example SQClassDef usage (see testSqPlus2.cpp): ===
1945
SQClassDef<NewTestObj> sqClass(sqT("NewTestObj");
1946
sqClass.func(NewTestObj::newtestR1,sqT("newtestR1"));
1947
sqClass.var(&NewTestObj::val,sqT("val"));
1948
sqClass.var(&NewTestObj::s1,sqT("s1"));
1949
sqClass.var(&NewTestObj::s2,sqT("s2"));
1950
sqClass.funcVarArgs(&NewTestObj::multiArgs,sqT("multiArgs"));
1954
SQClassDef<NewTestObj>(sqT("NewTestObj").
1955
func(NewTestObj::newtestR1,sqT("newtestR1")).
1956
var(&NewTestObj::val,sqT("val")).
1957
var(&NewTestObj::s1,sqT("s1")).
1958
var(&NewTestObj::s2,sqT("s2")).
1959
funcVarArgs(NewTestObj::multiArgs,sqT("multiArgs"));
1962
// === Macros for old style registration. SQClassDef registration is now easier to use (SQ_DECLARE_CLASS() is not needed) ===
1964
#define SQ_DECLARE_CLASS(CLASSNAME) \
1965
static SQInteger _##CLASSNAME##_release(SQUserPointer up,SQInteger size) { \
1967
CLASSNAME * self = (CLASSNAME *)up; \
1972
static SQInteger _##CLASSNAME##_constructor(HSQUIRRELVM v) { \
1973
CLASSNAME * pc = new CLASSNAME(); \
1974
sq_setinstanceup(v,1,pc); \
1975
sq_setreleasehook(v,1,_##CLASSNAME##_release); \
1979
#define SQ_REGISTER_CLASS(CLASSNAME) \
1980
RegisterClassType(SquirrelVM::GetVMPtr(),sqT(#CLASSNAME),_##CLASSNAME##_constructor)
1982
#define SQ_REGISTER_INSTANCE(NEWSQCLASS,CCLASS,FUNCNAME) \
1983
RegisterInstance(SquirrelVM::GetVMPtr(),NEWSQCLASS.GetObjectHandle(),*(CCLASS *)0,&CCLASS::FUNCNAME,sqT(#FUNCNAME));
1985
#define SQ_REGISTER_INSTANCE_VARARGS(NEWSQCLASS,CCLASS,FUNCNAME) \
1986
RegisterInstanceVarArgs(SquirrelVM::GetVMPtr(),NEWSQCLASS.GetObjectHandle(),*(CCLASS *)0,&CCLASS::FUNCNAME,sqT(#FUNCNAME));
1988
#define SQ_REGISTER_INSTANCE_VARIABLE(NEWSQCLASS,CCLASS,VARNAME) \
1989
RegisterInstanceVariable(NEWSQCLASS,&((CCLASS *)0)->VARNAME,sqT(#VARNAME));
1991
#if defined(USE_ARGUMENT_DEPENDANT_OVERLOADS) && defined(_MSC_VER)
1992
#pragma warning (default:4675)
1995
}; // namespace SqPlus
1997
#endif //_SQ_PLUS_H_