805 lines
28 KiB
C++
805 lines
28 KiB
C++
|
// testSqPlus.cpp
|
||
|
// Created by John Schultz 9/5/2005
|
||
|
// Free for any use.
|
||
|
|
||
|
#include <stdarg.h>
|
||
|
#include <stdio.h>
|
||
|
#include "sqplus.h"
|
||
|
|
||
|
using namespace SqPlus;
|
||
|
|
||
|
struct CTestObj {
|
||
|
float x;
|
||
|
float y;
|
||
|
float z;
|
||
|
CTestObj() {
|
||
|
x = y = z = 0.f;
|
||
|
}
|
||
|
void update(float t) {
|
||
|
x += t;
|
||
|
} // update
|
||
|
void print(void) {
|
||
|
SQChar buff[256];
|
||
|
scsprintf(buff,_SC("x: %f\n"),x);
|
||
|
// OutputDebugString(buff);
|
||
|
SCPUTS(buff);
|
||
|
} // print
|
||
|
};
|
||
|
|
||
|
_DECL_CLASS(TestObj);
|
||
|
|
||
|
_IMPL_NATIVE_CONSTRUCTION(TestObj,CTestObj);
|
||
|
|
||
|
_MEMBER_FUNCTION_IMPL(TestObj,constructor) {
|
||
|
CTestObj * newv = NULL;
|
||
|
StackHandler sa(v);
|
||
|
int nparams = sa.GetParamCount();
|
||
|
newv = new CTestObj();
|
||
|
return construct_TestObj(newv);
|
||
|
}
|
||
|
|
||
|
_MEMBER_FUNCTION_IMPL(TestObj,_set) {
|
||
|
StackHandler sa(v);
|
||
|
_CHECK_SELF(CTestObj,TestObj);
|
||
|
const SQChar *s = sa.GetString(2);
|
||
|
int index = s?s[0]:sa.GetInt(2);
|
||
|
switch(index) {
|
||
|
case 0: case 'x': case 'r':
|
||
|
return sa.Return(self->x = sa.GetFloat(3));
|
||
|
break;
|
||
|
case 1: case 'y': case 'g':
|
||
|
return sa.Return(self->y = sa.GetFloat(3));
|
||
|
break;
|
||
|
case 2: case 'z': case 'b':
|
||
|
return sa.Return(self->z = sa.GetFloat(3));
|
||
|
break;
|
||
|
} // switch
|
||
|
return SQ_ERROR;
|
||
|
}
|
||
|
|
||
|
_MEMBER_FUNCTION_IMPL(TestObj,_get) {
|
||
|
StackHandler sa(v);
|
||
|
_CHECK_SELF(CTestObj,TestObj);
|
||
|
const SQChar *s = sa.GetString(2);
|
||
|
if(s && (s[1] != 0)) return SQ_ERROR;
|
||
|
int index = s && (s[1] == 0)?s[0]:sa.GetInt(2);
|
||
|
switch(index) {
|
||
|
case 0: case 'x': case 'r': return sa.Return(self->x); break;
|
||
|
case 1: case 'y': case 'g': return sa.Return(self->y); break;
|
||
|
case 2: case 'z': case 'b': return sa.Return(self->z); break;
|
||
|
} // switch
|
||
|
return SQ_ERROR;
|
||
|
}
|
||
|
|
||
|
_MEMBER_FUNCTION_IMPL(TestObj,update) {
|
||
|
StackHandler sa(v);
|
||
|
_CHECK_SELF(CTestObj,TestObj);
|
||
|
SQObjectType type = (SQObjectType)sa.GetType(2);
|
||
|
if (type == OT_FLOAT || type == OT_INTEGER) {
|
||
|
float t = sa.GetFloat(2);
|
||
|
self->update(t);
|
||
|
} else {
|
||
|
SQChar buff[256];
|
||
|
scsprintf(buff,_SC("Invalid type for CTestObj::update(float): type %d\n"),type);
|
||
|
// OutputDebugString(buff);
|
||
|
SCPUTS(buff);
|
||
|
} // if
|
||
|
return SQ_OK;;
|
||
|
}
|
||
|
|
||
|
_MEMBER_FUNCTION_IMPL(TestObj,print) {
|
||
|
StackHandler sa(v);
|
||
|
_CHECK_SELF(CTestObj,TestObj);
|
||
|
SQChar buff[256];
|
||
|
scsprintf(buff,_SC("x: %f y: %f z: %f\n"),self->x,self->y,self->z);
|
||
|
// OutputDebugString(buff);
|
||
|
SCPUTS(buff);
|
||
|
// return sa.ThrowError(_SC("Error initializing the device"));
|
||
|
return SQ_OK;;
|
||
|
}
|
||
|
|
||
|
_MEMBER_FUNCTION_IMPL(TestObj,_print) {
|
||
|
_CHECK_SELF(CTestObj,TestObj);
|
||
|
SCPUTS(_SC("_print: "));
|
||
|
return __TestObj_print(v);
|
||
|
}
|
||
|
|
||
|
_BEGIN_CLASS(TestObj)
|
||
|
_MEMBER_FUNCTION(TestObj,constructor,1,_SC("x")) // x = instance ('self/this' not yet created), no arguments.
|
||
|
_MEMBER_FUNCTION(TestObj,_set,3,_SC("xs|n")) // x = instance, string, or int/float, as .x, .y, .z, or [0], [1], [2].
|
||
|
_MEMBER_FUNCTION(TestObj,_get,2,_SC("xs|n")) // x = instance, string, or int/float, as .x, .y, .z, or [0], [1], [2].
|
||
|
_MEMBER_FUNCTION(TestObj,update,2,_SC("xn")) // x = instance (this), n = int or float.
|
||
|
_MEMBER_FUNCTION(TestObj,print,1,_SC("x")) // x = instance (this).
|
||
|
_MEMBER_FUNCTION(TestObj,_print,1,_SC("x")) // x = instance (this).
|
||
|
_END_CLASS(TestObj)
|
||
|
|
||
|
#ifdef SQUNICODE
|
||
|
#define scvprintf vwprintf
|
||
|
#else
|
||
|
#define scvprintf vprintf
|
||
|
#endif
|
||
|
|
||
|
void printfunc(HSQUIRRELVM v,const SQChar *s,...) {
|
||
|
va_list arglist;
|
||
|
va_start(arglist, s);
|
||
|
scvprintf(s, arglist);
|
||
|
va_end(arglist);
|
||
|
}
|
||
|
|
||
|
int testFunc(HSQUIRRELVM v) {
|
||
|
StackHandler sa(v);
|
||
|
int paramCount = sa.GetParamCount();
|
||
|
scprintf(_SC("testFunc: numParams[%d]\n"),paramCount);
|
||
|
for (int i=1; i <= paramCount; i++) {
|
||
|
scprintf(_SC("param[%d]: "),i);
|
||
|
switch(sa.GetType(i)) {
|
||
|
case OT_TABLE: scprintf(_SC("OT_TABLE[0x%x]\n"),sa.GetObjectHandle(i)); break;
|
||
|
case OT_INTEGER: scprintf(_SC("OT_INTEGER[%d]\n"),sa.GetInt(i)); break;
|
||
|
case OT_FLOAT: scprintf(_SC("OT_FLOAT[%f]\n"),sa.GetFloat(i)); break;
|
||
|
case OT_STRING: scprintf(_SC("OT_STRING[%s]\n"),sa.GetString(i)); break;
|
||
|
default:
|
||
|
scprintf(_SC("TYPEID[%d]\n"),sa.GetType(i));
|
||
|
} // switch
|
||
|
} // for
|
||
|
return SQ_OK;
|
||
|
} // testFunc
|
||
|
|
||
|
// === BEGIN User Pointer version ===
|
||
|
#if 0
|
||
|
|
||
|
int setVarFunc2(HSQUIRRELVM v) {
|
||
|
StackHandler sa(v);
|
||
|
if (sa.GetType(1) == OT_TABLE) {
|
||
|
HSQOBJECT htable = sa.GetObjectHandle(1);
|
||
|
SquirrelObject table(htable);
|
||
|
const SQChar * el = sa.GetString(2);
|
||
|
SquirrelObject upValMapPtr = table.GetValue(_SC("_uvp"));
|
||
|
SquirrelObject upValMapType = table.GetValue(_SC("_uvt"));
|
||
|
if (!upValMapType.Exists(el)) {
|
||
|
return SQ_ERROR;
|
||
|
} // if
|
||
|
int vType = upValMapType.GetInt(el);
|
||
|
switch (vType) {
|
||
|
case TypeInfo<int>::TypeID: {
|
||
|
int * val = (int *)upValMapPtr.GetUserPointer(el);
|
||
|
if (val) {
|
||
|
*val = sa.GetInt(3);
|
||
|
return sa.Return(*val);
|
||
|
} else {
|
||
|
return sa.Return(-1);
|
||
|
} // if
|
||
|
} // case
|
||
|
case TypeInfo<float>::TypeID: {
|
||
|
float * val = (float *)upValMapPtr.GetUserPointer(el);
|
||
|
if (val) {
|
||
|
*val = sa.GetFloat(3);
|
||
|
return sa.Return(*val);
|
||
|
} else {
|
||
|
return sa.Return(-1);
|
||
|
} // if
|
||
|
} // case
|
||
|
case TypeInfo<bool>::TypeID: {
|
||
|
bool * val = (bool *)upValMapPtr.GetUserPointer(el);
|
||
|
if (val) {
|
||
|
*val = sa.GetBool(3) ? true : false;
|
||
|
return sa.Return(*val);
|
||
|
} else {
|
||
|
return sa.Return(-1);
|
||
|
} // if
|
||
|
} // case
|
||
|
} // switch
|
||
|
} // if
|
||
|
return SQ_ERROR;
|
||
|
} // setVarFunc2
|
||
|
|
||
|
int getVarFunc2(HSQUIRRELVM v) {
|
||
|
StackHandler sa(v);
|
||
|
if (sa.GetType(1) == OT_TABLE) {
|
||
|
HSQOBJECT htable = sa.GetObjectHandle(1);
|
||
|
SquirrelObject table(htable);
|
||
|
int type = sa.GetType(2);
|
||
|
const SQChar * el = sa.GetString(2);
|
||
|
SquirrelObject upValMap = table.GetValue(_SC("_uvp"));
|
||
|
SquirrelObject upValMapType = table.GetValue(_SC("_uvt"));
|
||
|
if (!upValMapType.Exists(el)) {
|
||
|
return SQ_ERROR;
|
||
|
} // if
|
||
|
int vType = upValMapType.GetInt(el);
|
||
|
switch (vType) {
|
||
|
case TypeInfo<int>::TypeID: {
|
||
|
int * val = (int *)upValMap.GetUserPointer(el);
|
||
|
if (val) {
|
||
|
return sa.Return(*val);
|
||
|
} else {
|
||
|
return sa.Return(-1);
|
||
|
} // if
|
||
|
} // case
|
||
|
case TypeInfo<float>::TypeID: {
|
||
|
float * val = (float *)upValMap.GetUserPointer(el);
|
||
|
if (val) {
|
||
|
return sa.Return(*val);
|
||
|
} else {
|
||
|
return sa.Return(-1);
|
||
|
} // if
|
||
|
} // case
|
||
|
case TypeInfo<bool>::TypeID: {
|
||
|
bool * val = (bool *)upValMap.GetUserPointer(el);
|
||
|
if (val) {
|
||
|
return sa.Return(*val);
|
||
|
} else {
|
||
|
return sa.Return(-1);
|
||
|
} // if
|
||
|
} // case
|
||
|
} // switch
|
||
|
} // if
|
||
|
return SQ_ERROR;
|
||
|
} // getVarFunc2
|
||
|
|
||
|
template<typename T>
|
||
|
void bindVariable2(SquirrelObject & so,T & var,const SQChar * scriptVarName) {
|
||
|
SquirrelObject __upValMapPtr;
|
||
|
SquirrelObject __upValMapType;
|
||
|
|
||
|
if (so.Exists(_SC("_uvp"))) {
|
||
|
__upValMapPtr = so.GetValue(_SC("_uvp"));
|
||
|
__upValMapType = so.GetValue(_SC("_uvt"));
|
||
|
} else {
|
||
|
__upValMapPtr = SquirrelVM::CreateTable();
|
||
|
__upValMapType = SquirrelVM::CreateTable();
|
||
|
} // if
|
||
|
|
||
|
int varType = TypeInfo<T>::TypeID;
|
||
|
__upValMapPtr.SetUserPointer(scriptVarName,&var);
|
||
|
__upValMapType.SetValue(scriptVarName,varType);
|
||
|
|
||
|
so.SetValue(_SC("_uvp"),__upValMapPtr);
|
||
|
so.SetValue(_SC("_uvt"),__upValMapType);
|
||
|
|
||
|
SquirrelObject delegate = so.GetDelegate();
|
||
|
if (!delegate.Exists(_SC("_set"))) {
|
||
|
delegate = SquirrelVM::CreateTable();
|
||
|
SquirrelVM::CreateFunction(delegate,"_set",setVarFunc2,_SC("sn|b")); // String var name = number(int or float) or bool.
|
||
|
SquirrelVM::CreateFunction(delegate,"_get",getVarFunc2,_SC("s")); // String var name.
|
||
|
so.SetDelegate(delegate);
|
||
|
} // if
|
||
|
|
||
|
} // bindVariable2
|
||
|
#endif
|
||
|
|
||
|
// === BEGIN Old, initial test versions. ===
|
||
|
|
||
|
int setIntFunc(HSQUIRRELVM v) {
|
||
|
StackHandler sa(v);
|
||
|
if (sa.GetType(1) == OT_TABLE) {
|
||
|
HSQOBJECT htable = sa.GetObjectHandle(1);
|
||
|
SquirrelObject table(htable);
|
||
|
const SQChar * el = sa.GetString(2);
|
||
|
SquirrelObject upValMap = table.GetValue(_SC("upValMap"));
|
||
|
int * val = (int *)upValMap.GetUserPointer(el);
|
||
|
if (val) {
|
||
|
*val = sa.GetInt(3);
|
||
|
return sa.Return(*val);
|
||
|
} else {
|
||
|
return sa.Return(-1);
|
||
|
} // if
|
||
|
} // if
|
||
|
return SQ_ERROR;
|
||
|
} // setIntFunc
|
||
|
|
||
|
int getIntFunc(HSQUIRRELVM v) {
|
||
|
StackHandler sa(v);
|
||
|
if (sa.GetType(1) == OT_TABLE) {
|
||
|
HSQOBJECT htable = sa.GetObjectHandle(1);
|
||
|
SquirrelObject table(htable);
|
||
|
int type = sa.GetType(2);
|
||
|
const SQChar * el = sa.GetString(2);
|
||
|
SquirrelObject upValMap = table.GetValue(_SC("upValMap"));
|
||
|
int * val = (int *)upValMap.GetUserPointer(el);
|
||
|
if (val) {
|
||
|
return sa.Return(*val);
|
||
|
} else {
|
||
|
return sa.Return(-1);
|
||
|
} // if
|
||
|
} // if
|
||
|
return SQ_ERROR;
|
||
|
} // getIntFunc
|
||
|
|
||
|
// === END Old, initial tests versions. ===
|
||
|
|
||
|
_DECL_STATIC_NAMESPACE(GB); // Globals
|
||
|
|
||
|
_MEMBER_FUNCTION_IMPL(GB,Update) {
|
||
|
StackHandler sa(v);
|
||
|
scprintf(_SC("GB.Update()\n"));
|
||
|
return sa.Return(true);
|
||
|
}
|
||
|
|
||
|
enum {TEST_CONST=123};
|
||
|
|
||
|
_BEGIN_NAMESPACE(GB)
|
||
|
_MEMBER_FUNCTION(GB,Update,0,0)
|
||
|
_BEGIN_NAMESPACE_CONSTANTS(GB)
|
||
|
_CONSTANT_IMPL(TEST_CONST,OT_INTEGER)
|
||
|
_END_NAMESPACE(GB,NULL)
|
||
|
|
||
|
#if 0
|
||
|
int getVarName(HSQUIRRELVM v) {
|
||
|
StackHandler sa(v);
|
||
|
const SQChar * varName = sq_getlocal(v,1,0);
|
||
|
return sa.Return(varName);
|
||
|
} // getVarName
|
||
|
#endif
|
||
|
|
||
|
void newtest(void) {
|
||
|
scprintf(_SC("NewTest\n"));
|
||
|
}
|
||
|
|
||
|
SQChar * newtestR1(const SQChar * inString) {
|
||
|
scprintf(_SC("NewTestR1: %s\n"),inString);
|
||
|
return _SC("Returned String");
|
||
|
}
|
||
|
|
||
|
struct NewTestObj {
|
||
|
ScriptStringVar64 s1;
|
||
|
ScriptStringVar32 s2;
|
||
|
int pad;
|
||
|
int val;
|
||
|
int c1;
|
||
|
ScriptStringVar8 c2; // 8 char plus null (max string is 8 printable chars).
|
||
|
NewTestObj() : val(777) {
|
||
|
s1 = _SC("s1");
|
||
|
s2 = _SC("s2");
|
||
|
c1 = 996;
|
||
|
c2 = _SC("It's a 997"); // Prints: "It's a 9", as only 8 chars in static buffer (plus null).
|
||
|
}
|
||
|
void newtest(void) {
|
||
|
scprintf(_SC("NewTest: %d\n"),val);
|
||
|
}
|
||
|
SQChar * newtestR1(const SQChar * inString) {
|
||
|
scprintf(_SC("NewTestR1: Member var val is %d, function arg is %s\n"),val,inString);
|
||
|
return _SC("Returned String");
|
||
|
}
|
||
|
|
||
|
int multiArgs(HSQUIRRELVM v) {
|
||
|
StackHandler sa(v);
|
||
|
int paramCount = sa.GetParamCount();
|
||
|
int p1 = sa.GetInt(2);
|
||
|
int p2 = sa.GetInt(3);
|
||
|
int p3 = sa.GetInt(4);
|
||
|
return 0;
|
||
|
} // multiArgs
|
||
|
|
||
|
int _set(HSQUIRRELVM v) {
|
||
|
StackHandler sa(v);
|
||
|
int paramCount = sa.GetParamCount();
|
||
|
const SQChar * el = sa.GetString(2);
|
||
|
val = sa.GetInt(3);
|
||
|
return sa.Return(val);
|
||
|
// return setInstanceVarFunc(v);
|
||
|
}
|
||
|
|
||
|
int _get(HSQUIRRELVM v) {
|
||
|
StackHandler sa(v);
|
||
|
int paramCount = sa.GetParamCount();
|
||
|
// return getInstanceVarFunc(v);
|
||
|
return sa.Return(val);
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
struct CustomTestObj {
|
||
|
ScriptStringVar128 name;
|
||
|
int val;
|
||
|
bool state;
|
||
|
CustomTestObj() : val(0), state(false) { name = _SC("empty"); }
|
||
|
CustomTestObj(const SQChar * _name,int _val,bool _state) : val(_val), state(_state) {
|
||
|
name = _name;
|
||
|
}
|
||
|
static int construct(HSQUIRRELVM v) {
|
||
|
StackHandler sa(v);
|
||
|
int paramCount = sa.GetParamCount();
|
||
|
if (paramCount == 1) {
|
||
|
return PostConstruct(v,new CustomTestObj(),release);
|
||
|
} if (paramCount == 4) {
|
||
|
return PostConstruct(v,new CustomTestObj(sa.GetString(2),sa.GetInt(3),sa.GetBool(4)?true:false),release);
|
||
|
} // if
|
||
|
return sq_throwerror(v,_SC("Invalid Constructor arguments"));
|
||
|
} // construct
|
||
|
|
||
|
SQ_DECLARE_RELEASE(CustomTestObj)
|
||
|
|
||
|
// Member function that handles variable types.
|
||
|
int varArgTypes(HSQUIRRELVM v) {
|
||
|
StackHandler sa(v);
|
||
|
int paramCount = sa.GetParamCount();
|
||
|
if (sa.GetType(2) == OT_INTEGER) {
|
||
|
val = sa.GetInt(2);
|
||
|
} // if
|
||
|
if (sa.GetType(2) == OT_STRING) {
|
||
|
name = sa.GetString(2);
|
||
|
} // if
|
||
|
if (sa.GetType(3) == OT_INTEGER) {
|
||
|
val = sa.GetInt(3);
|
||
|
} // if
|
||
|
if (sa.GetType(3) == OT_STRING) {
|
||
|
name = sa.GetString(3);
|
||
|
} // if
|
||
|
return 0;
|
||
|
} // varArgTypes
|
||
|
|
||
|
// Member function that handles variable types and has variable return types+count.
|
||
|
int varArgTypesAndCount(HSQUIRRELVM v) {
|
||
|
StackHandler sa(v);
|
||
|
int paramCount = sa.GetParamCount();
|
||
|
SQObjectType type1 = (SQObjectType)sa.GetType(1); // Always OT_INSTANCE
|
||
|
SQObjectType type2 = (SQObjectType)sa.GetType(2);
|
||
|
SQObjectType type3 = (SQObjectType)sa.GetType(3);
|
||
|
SQObjectType type4 = (SQObjectType)sa.GetType(4);
|
||
|
int returnCount = 0;
|
||
|
if (paramCount == 3) {
|
||
|
sq_pushinteger(v,val);
|
||
|
returnCount = 1;
|
||
|
} else if (paramCount == 4) {
|
||
|
sq_pushinteger(v,val);
|
||
|
sq_pushstring(v,name,-1);
|
||
|
returnCount = 2;
|
||
|
} // if
|
||
|
return returnCount;
|
||
|
} //
|
||
|
|
||
|
int noArgsVariableReturn(HSQUIRRELVM v) {
|
||
|
if (val == 123) {
|
||
|
val++;
|
||
|
return 0; // This will print (null).
|
||
|
} else if (val == 124) {
|
||
|
sq_pushinteger(v,val); // Will return int:124.
|
||
|
val++;
|
||
|
return 1;
|
||
|
} else if (val == 125) {
|
||
|
sq_pushinteger(v,val);
|
||
|
name = _SC("Case 125");
|
||
|
sq_pushstring(v,name,-1);
|
||
|
val = 123; // reset
|
||
|
return 2;
|
||
|
} // if
|
||
|
return 0;
|
||
|
} // noArgsVariableReturn
|
||
|
|
||
|
// Registered with func() instead of funcVarArgs(): fixed (single) return type.
|
||
|
const SQChar * variableArgsFixedReturnType(HSQUIRRELVM v) {
|
||
|
StackHandler sa(v);
|
||
|
int paramCount = sa.GetParamCount();
|
||
|
SQObjectType type1 = (SQObjectType)sa.GetType(1); // Always OT_INSTANCE
|
||
|
SQObjectType type2 = (SQObjectType)sa.GetType(2);
|
||
|
SQObjectType type3 = (SQObjectType)sa.GetType(3);
|
||
|
if (paramCount == 1) {
|
||
|
return _SC("No Args");
|
||
|
} else if (paramCount == 2) {
|
||
|
return _SC("One Arg");
|
||
|
} else if (paramCount == 3) {
|
||
|
return _SC("Two Args");
|
||
|
} // if
|
||
|
return _SC("More than two args");
|
||
|
} // variableArgsFixedReturnType
|
||
|
|
||
|
void manyArgs(int i,float f,bool b,const SQChar * s) {
|
||
|
scprintf(_SC("i: %d, f: %f, b: %s, s: %s\n"),i,f,b?_SC("true"):_SC("false"),s);
|
||
|
} // manyArgs
|
||
|
|
||
|
float manyArgsR1(int i,float f,bool b,const SQChar * s) {
|
||
|
manyArgs(i,f,b,s);
|
||
|
return i+f;
|
||
|
} // manyArgsR1
|
||
|
|
||
|
};
|
||
|
|
||
|
#if 0
|
||
|
struct Base {
|
||
|
int val1;
|
||
|
ScriptStringVar16 nameBase;
|
||
|
Base() : nameBase(_SC("Base")) {
|
||
|
val1 = 123;
|
||
|
}
|
||
|
void funcBase(void) {
|
||
|
scprintf(_SC("Val1: %d, Name: %s\n"),val1,nameBase.s);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
struct Derived {
|
||
|
int val2;
|
||
|
ScriptStringVar16 nameDerived;
|
||
|
Derived() : nameDerived(_SC("Derived")), val2(456) {
|
||
|
val2 = 456;
|
||
|
}
|
||
|
void funcDerived(void) {
|
||
|
scprintf(_SC("Val2: %d, Name: %s\n"),val2,nameDerived.s);
|
||
|
}
|
||
|
};
|
||
|
#endif
|
||
|
|
||
|
//SQ_DECLARE_CLASS(NewTestObj);
|
||
|
|
||
|
class TestSqPlus {
|
||
|
public:
|
||
|
void init(void) {
|
||
|
SquirrelVM::Init();
|
||
|
// sq_setprintfunc(SquirrelVM::GetVMPtr(),printfunc); //sets the print function.
|
||
|
_INIT_CLASS(TestObj);
|
||
|
_INIT_STATIC_NAMESPACE(GB);
|
||
|
} // if
|
||
|
|
||
|
TestSqPlus() {
|
||
|
init();
|
||
|
|
||
|
try {
|
||
|
HSQUIRRELVM v = SquirrelVM::GetVMPtr();
|
||
|
|
||
|
// === BEGIN Global Function binding tests ===
|
||
|
|
||
|
// Implemented as SquirrelVM::CreateFunction(rootTable,func,name,typeMask);
|
||
|
SquirrelVM::CreateFunctionGlobal(&testFunc,_SC("testFunc0"));
|
||
|
SquirrelVM::CreateFunctionGlobal(&testFunc,_SC("testFuncN"),_SC("n"));
|
||
|
SquirrelVM::CreateFunctionGlobal(&testFunc,_SC("testFuncS"),_SC("s"));
|
||
|
|
||
|
// === Register Standard Functions ===
|
||
|
|
||
|
RegisterGlobal(v,&newtest,_SC("test"));
|
||
|
RegisterGlobal(v,&newtestR1,_SC("testR1"));
|
||
|
|
||
|
// === Register Member Functions to existing classes (as opposed to instances of classes) ===
|
||
|
|
||
|
NewTestObj t1,t2,t3;
|
||
|
t1.val = 123;
|
||
|
t2.val = 456;
|
||
|
t3.val = 789;
|
||
|
RegisterGlobal(v,t1,&NewTestObj::newtest,_SC("testObj_newtest1"));
|
||
|
RegisterGlobal(v,t2,&NewTestObj::newtest,_SC("testObj_newtest2")); // Register newtest() again with different name and object pointer.
|
||
|
SquirrelObject tr = SquirrelVM::GetRootTable(); // Can be any object supporting closures (functions).
|
||
|
Register(v,tr.GetObjectHandle(),t3,&NewTestObj::newtestR1,_SC("testObj_newtestR1")); // Return value version.
|
||
|
|
||
|
// === END Global Function binding tests ===
|
||
|
|
||
|
// === BEGIN Class Instance tests ===
|
||
|
|
||
|
#if 0
|
||
|
SQClassDef<NewTestObj> sqClass(_SC("NewTestObj"));
|
||
|
sqClass.func(&NewTestObj::newtestR1,_SC("newtestR1"));
|
||
|
sqClass.var(&NewTestObj::val,_SC("val"));
|
||
|
sqClass.var(&NewTestObj::s1,_SC("s1"));
|
||
|
sqClass.var(&NewTestObj::s2,_SC("s2"));
|
||
|
sqClass.var(&NewTestObj::c1,_SC("c1"),VAR_ACCESS_READ_ONLY);
|
||
|
sqClass.var(&NewTestObj::c2,_SC("c2"),VAR_ACCESS_READ_ONLY);
|
||
|
sqClass.funcVarArgs(&NewTestObj::multiArgs,_SC("multiArgs"));
|
||
|
#else
|
||
|
SQClassDef<NewTestObj>(_SC("NewTestObj")).
|
||
|
func(&NewTestObj::newtestR1,_SC("newtestR1")).
|
||
|
var(&NewTestObj::val,_SC("val")).
|
||
|
var(&NewTestObj::s1,_SC("s1")).
|
||
|
var(&NewTestObj::s2,_SC("s2")).
|
||
|
var(&NewTestObj::c1,_SC("c1"),VAR_ACCESS_READ_ONLY).
|
||
|
var(&NewTestObj::c2,_SC("c2"),VAR_ACCESS_READ_ONLY).
|
||
|
funcVarArgs(&NewTestObj::multiArgs,_SC("multiArgs"));
|
||
|
#endif
|
||
|
|
||
|
SQClassDef<CustomTestObj> customClass(_SC("CustomTestObj"));
|
||
|
customClass.staticFuncVarArgs(&CustomTestObj::construct,_SC("constructor"),_SC("snb")); // string, number, bool (all types must match).
|
||
|
customClass.funcVarArgs(&CustomTestObj::varArgTypes,_SC("varArgTypes"),_SC("s|ns|ns|ns|n")); // string or number + string or number.
|
||
|
customClass.funcVarArgs(&CustomTestObj::varArgTypesAndCount,_SC("varArgTypesAndCount"),_SC("*")); // "*"): no type or count checking.
|
||
|
customClass.funcVarArgs(&CustomTestObj::noArgsVariableReturn,_SC("noArgsVariableReturn")); // No type string means no arguments allowed.
|
||
|
customClass.func(&CustomTestObj::variableArgsFixedReturnType,_SC("variableArgsFixedReturnType")); // Variables args, fixed return type.
|
||
|
customClass.func(&CustomTestObj::manyArgs,_SC("manyArgs")); // Many args, type checked.
|
||
|
customClass.func(&CustomTestObj::manyArgsR1,_SC("manyArgsR1")); // Many args, type checked, one return value.
|
||
|
|
||
|
// Old macro-based method. Must use SQ_DECLARE_CLASS() macro above.
|
||
|
#if 0
|
||
|
SquirrelObject newClass = SQ_REGISTER_CLASS(NewTestObj);
|
||
|
SQ_REGISTER_INSTANCE(newClass,NewTestObj,newtestR1);
|
||
|
// Currently, can use either automatic variable handling OR manual handling (but not both at once).
|
||
|
#if 1
|
||
|
SQ_REGISTER_INSTANCE_VARIABLE(newClass,NewTestObj,val); // _set/_get will be defined to use automatic methods for val.
|
||
|
#else
|
||
|
SQ_REGISTER_INSTANCE_VARARGS(newClass,NewTestObj,_set); // _set is now defined and won't be overridden.
|
||
|
SQ_REGISTER_INSTANCE_VARARGS(newClass,NewTestObj,_get);
|
||
|
SQ_REGISTER_INSTANCE_VARIABLE(newClass,NewTestObj,val); // Access will be through _set/_get member functions above, not automatic methods.
|
||
|
#endif
|
||
|
|
||
|
#if 1
|
||
|
// With an HSQUIRRELVM argument, can handle variable args, and when registered this way can return multiple values.
|
||
|
SQ_REGISTER_INSTANCE_VARARGS(newClass,NewTestObj,multiArgs);
|
||
|
#else
|
||
|
// With an HSQUIRRELVM argument, can handle variable args, but can only return one value (defined by the function definition).
|
||
|
SQ_REGISTER_INSTANCE(newClass,NewTestObj,multiArgs);
|
||
|
#endif
|
||
|
#endif
|
||
|
|
||
|
#if 1
|
||
|
SquirrelObject testReg0 = SquirrelVM::CompileBuffer(_SC(" co <- CustomTestObj(\"hello\",123,true); co.varArgTypes(\"str\",123,123,\"str\"); co.varArgTypes(123,\"str\",\"str\",123); "));
|
||
|
SquirrelVM::RunScript(testReg0);
|
||
|
|
||
|
SquirrelObject testReg0a = SquirrelVM::CompileBuffer(_SC(" print(co.varArgTypesAndCount(1,true)); print(co.varArgTypesAndCount(2,false,3.)); print(\"\\n\"); "));
|
||
|
SquirrelVM::RunScript(testReg0a);
|
||
|
|
||
|
SquirrelObject testReg0b = SquirrelVM::CompileBuffer(_SC(" print(co.noArgsVariableReturn()); print(co.noArgsVariableReturn()); print(co.noArgsVariableReturn()); print(\"\\n\"); "));
|
||
|
SquirrelVM::RunScript(testReg0b);
|
||
|
|
||
|
SquirrelObject testReg0c = SquirrelVM::CompileBuffer(_SC(" print(co.variableArgsFixedReturnType(1)); print(co.variableArgsFixedReturnType(1,2)); print(co.variableArgsFixedReturnType(1,2,3)); print(\"\\n\"); "));
|
||
|
SquirrelVM::RunScript(testReg0c);
|
||
|
|
||
|
SquirrelObject testReg0d = SquirrelVM::CompileBuffer(_SC(" co.manyArgs(111,222.2,true,\"Hello\"); print(co.manyArgsR1(333,444.3,false,\"World\")); print(\"\\n\"); "));
|
||
|
SquirrelVM::RunScript(testReg0d);
|
||
|
#endif
|
||
|
|
||
|
// Inheriting from an existing base class in this way is not currently supported.
|
||
|
// Requires either a Squirrel language/behavior change, or extra code at the interface
|
||
|
// layer to allocate memory and call constructor of parent class (and perhaps
|
||
|
// handle constructor args) store pointer in UserData, and handle proper variable access
|
||
|
// (get correct class/struct pointer) and member function calls (store class
|
||
|
// type/id in function up-var and search/hash for actual 'this' pointer for function call).
|
||
|
#if 0
|
||
|
SQClassDef<Base>(_SC("Base")).
|
||
|
var(&Base::nameBase,_SC("nameBase")).
|
||
|
func(&Base::funcBase,_SC("funcBase"));
|
||
|
|
||
|
SQClassDef<Derived>("Derived",_SC("Base")).
|
||
|
var(&Derived::nameDerived,_SC("nameDerived")).
|
||
|
func(&Derived::funcDerived,_SC("funcDerived"));
|
||
|
|
||
|
// SquirrelObject testBaseDerived = SquirrelVM::CompileBuffer(_SC(" local base = Base(); print(base.nameBase); local derived = Derived(); print(\"NameBase: \"+derived.nameBase+\" NameDerived: \"+derived.nameDerived); derived.funcBase(); "));
|
||
|
SquirrelObject testBaseDerived = SquirrelVM::CompileBuffer(_SC(" local derived = Derived(); print(\"NameBase: \"+derived.nameBase+\" NameDerived: \"+derived.nameDerived); derived.funcBase(); "));
|
||
|
SquirrelVM::RunScript(testBaseDerived);
|
||
|
#endif
|
||
|
|
||
|
#if 1
|
||
|
SquirrelObject testReg1a = SquirrelVM::CompileBuffer(_SC(" co <- CustomTestObj(\"hello\",123,true); co.noArgsVariableReturn(); local t = NewTestObj(); print(\"C1: \"+t.c1); print(\"C2: \"+t.c2); // t.c1 = 123; "));
|
||
|
SquirrelVM::RunScript(testReg1a);
|
||
|
|
||
|
// Constant test (read only var). Var can change on C++ side, but not on script side.
|
||
|
try {
|
||
|
SquirrelObject testRegConstant = SquirrelVM::CompileBuffer(_SC(" local t = NewTestObj(); t.c1 = 123; "));
|
||
|
SquirrelVM::RunScript(testRegConstant);
|
||
|
} // try
|
||
|
catch (SquirrelError & e) {
|
||
|
SQChar buff[256];
|
||
|
scsprintf(buff,_SC("Error: %s, %s\n"),e.desc,_SC("Squirrel::TestConstant"));
|
||
|
// OutputDebugString(buff);
|
||
|
SCPUTS(buff);
|
||
|
} // catch
|
||
|
|
||
|
SquirrelObject testReg1 = SquirrelVM::CompileBuffer(_SC(" local t = NewTestObj(); t.newtestR1(\"Hello\"); t.val = 789; print(t.val); print(t.s1); print(t.s2); t.s1 = \"New S1\"; print(t.s1); "));
|
||
|
SquirrelVM::RunScript(testReg1);
|
||
|
|
||
|
SquirrelObject testReg2 = SquirrelVM::CompileBuffer(_SC(" local t = NewTestObj(); t.val = 789; print(t.val); t.val = 876; print(t.val); t.multiArgs(1,2,3); t.multiArgs(1,2,3,4); "));
|
||
|
SquirrelVM::RunScript(testReg2);
|
||
|
SquirrelObject testReg3 = SquirrelVM::CompileBuffer(_SC(" test(); local rv = testR1(\"Hello\"); print(rv); "));
|
||
|
SquirrelVM::RunScript(testReg3);
|
||
|
SquirrelObject testReg4 = SquirrelVM::CompileBuffer(_SC(" print(\"\\nMembers:\"); testObj_newtest1(); testObj_newtest2(); print(testObj_newtestR1(\"Hello Again\")); "));
|
||
|
SquirrelVM::RunScript(testReg4);
|
||
|
|
||
|
SquirrelObject defCallFunc = SquirrelVM::CompileBuffer(_SC(" function callMe(var) { print(\"I was called by: \"+var); return 123; }"));
|
||
|
SquirrelVM::RunScript(defCallFunc);
|
||
|
|
||
|
SquirrelObject root = SquirrelVM::GetRootTable();
|
||
|
|
||
|
// Get a function from the root table and call it.
|
||
|
SquirrelFunction<int> callFunc(_SC("callMe"));
|
||
|
int ival = callFunc(_SC("Squirrel"));
|
||
|
scprintf(_SC("IVal: %d\n"),ival);
|
||
|
ival = 0;
|
||
|
// Get a function from any table.
|
||
|
SquirrelFunction<int> callFunc2(root.GetObjectHandle(),_SC("callMe"));
|
||
|
ival = callFunc(456); // Argument count is checked; type is not.
|
||
|
|
||
|
// === END Class Instance tests ===
|
||
|
|
||
|
// === BEGIN macro-only class-registrated tests ===
|
||
|
// SquirrelVM::CreateFunctionGlobal(_SC("getName",getVarName,"*")); // * = any type.
|
||
|
// SquirrelObject main = SquirrelVM::CompileBuffer(_SC("local testObj = TestObj(); testObj.print(); testObj.update(\"ab\"); testObj.print()"));
|
||
|
// SquirrelObject main = SquirrelVM::CompileBuffer(_SC("local LF = \"\\n\"; local testObj = TestObj(); testObj.print(); testObj.update(1.5); testObj.print(); testObj.y += 10.; testObj.z = -1.; print(testObj.y+LF); print(\"Array: \"+testObj[0]+LF); print(testObj); print(LF); "));
|
||
|
// SquirrelObject main = SquirrelVM::CompileBuffer(_SC("local testObj = TestObj(); testObj.z = -1.; print(testObj); testFunc(); testFunc0(); testFuncN(1.); testFuncS(\"Hello\"); "));
|
||
|
// SquirrelObject main = SquirrelVM::CompileBuffer(_SC("testFunc0(); testFuncN(1); testFuncN(1.23); testFuncS(\"Hello\");"));
|
||
|
|
||
|
SquirrelObject main = SquirrelVM::CompileBuffer(_SC("table1 <- {key1=\"keyVal\",key2 = 123};\n if (\"key1\" in table1)\n print(\"Sq: Found it\");\n else\n print(\"Sq: Not found\");"));
|
||
|
SquirrelVM::RunScript(main);
|
||
|
SquirrelObject table1 = root.GetValue(_SC("table1"));
|
||
|
if (table1.Exists(_SC("key1"))) {
|
||
|
scprintf(_SC("C++: Found it.\n"));
|
||
|
} else {
|
||
|
scprintf(_SC("C++: Did not find it.\n"));
|
||
|
} // if
|
||
|
|
||
|
// === BEGIN Simple variable binding tests ===
|
||
|
|
||
|
int iVar = 777;
|
||
|
float fVar = 88.99f;
|
||
|
bool bVar = true;
|
||
|
BindVariable(root,&iVar,_SC("iVar"));
|
||
|
BindVariable(root,&fVar,_SC("fVar"));
|
||
|
BindVariable(root,&bVar,_SC("bVar"));
|
||
|
|
||
|
static ScriptStringVar128 testString;
|
||
|
scsprintf(testString,_SC("This is a test string"));
|
||
|
BindVariable(root,&testString,_SC("testString"));
|
||
|
|
||
|
// === END Simple variable binding tests ===
|
||
|
|
||
|
// === BEGIN Array Tests ===
|
||
|
|
||
|
SquirrelObject array = SquirrelVM::CreateArray(10);
|
||
|
int i;
|
||
|
for (i = 0; i < 10; i++) array.SetValue(i,i);
|
||
|
array.ArrayAppend(123); // int
|
||
|
array.ArrayAppend(true); // bool (must use bool and not SQBool (SQBool is treated as INT by compiler).
|
||
|
array.ArrayAppend(false); // bool (must use bool and not SQBool (SQBool is treated as INT by compiler).
|
||
|
array.ArrayAppend(123.456f); // float
|
||
|
array.ArrayAppend(_SC("string")); // string
|
||
|
array.ArrayAppend(456); // Will be popped and thrown away (below).
|
||
|
|
||
|
// Pop 3 items from array:
|
||
|
array.ArrayPop(SQFalse); // Don't retrieve the popped value (int:123).
|
||
|
SquirrelObject so1 = array.ArrayPop(); // Retrieve the popped value.
|
||
|
const SQChar * val1 = so1.ToString(); // Get string.
|
||
|
float val2 = array.ArrayPop().ToFloat(); // Pop and get float.
|
||
|
scprintf(_SC("[Popped values] Val1: %s, Val2: %f\n"),val1,val2);
|
||
|
|
||
|
int startIndex = array.Len();
|
||
|
array.ArrayExtend(10); // Implemented as: ArrayResize(Len()+amount).
|
||
|
for (i = startIndex; i < array.Len(); i++) array.SetValue(i,i*10);
|
||
|
root.SetValue(_SC("array"),array);
|
||
|
|
||
|
SquirrelObject arrayr = array.Clone(); // Get a copy as opposed to another reference.
|
||
|
arrayr.ArrayReverse();
|
||
|
root.SetValue(_SC("arrayr"),arrayr);
|
||
|
|
||
|
// === END Array Tests ===
|
||
|
|
||
|
// SquirrelObject test = SquirrelVM::CompileBuffer(_SC(" print(iVar); print(fVar); print(bVar); iVar += 1; fVar += 100.; bVar = false; print(iVar); print(fVar); print(bVar); xVar = 1; ")); // Test for xVar error.
|
||
|
// SquirrelObject test = SquirrelVM::CompileBuffer(_SC(" print(iVar); print(fVar); print(bVar); iVar += 1; fVar += 100.; bVar = false; print(iVar); print(fVar); print(bVar); print(testString); testString = \"New string value\"; print(testString);"));
|
||
|
SquirrelObject define_printArray = SquirrelVM::CompileBuffer(_SC(" function printArray(name,array) { print(name+\".len() = \"+array.len()); foreach(i, v in array) if (v != null) { if (typeof v == \"bool\") v = v ? \"true\" : \"false\"; print(\"[\"+i+\"]: \"+v); } } "));
|
||
|
SquirrelVM::RunScript(define_printArray);
|
||
|
SquirrelObject test = SquirrelVM::CompileBuffer(_SC(" printArray(\"array\",array); printArray(\"arrayr\",arrayr); "));
|
||
|
|
||
|
// SquirrelObject test = SquirrelVM::CompileBuffer(_SC(" iVar = 1; print(iVar); "));
|
||
|
// SquirrelObject test = SquirrelVM::CompileBuffer(_SC(" print(\"GB:\"+GB.TEST_CONST); GB.TEST_CONST += 1; GB.Update(); print(\"GB2:\"+GB.TEST_CONST); \n"));
|
||
|
|
||
|
SquirrelVM::RunScript(test);
|
||
|
#endif
|
||
|
|
||
|
} // try
|
||
|
catch (SquirrelError & e) {
|
||
|
// SquirrelVM::DumpStack();
|
||
|
SQChar buff[256];
|
||
|
scsprintf(buff,_SC("Error: %s, %s\n"),e.desc,_SC("Squirrel::TestObj"));
|
||
|
// OutputDebugString(buff);
|
||
|
SCPUTS(buff);
|
||
|
} // catch
|
||
|
|
||
|
}
|
||
|
|
||
|
~TestSqPlus() {
|
||
|
SquirrelVM::Shutdown();
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
void doTest(void) {
|
||
|
TestSqPlus testSqPlus;
|
||
|
} // doTest
|
||
|
|
||
|
int main(int argc,char * argv[]) {
|
||
|
|
||
|
// Run twice to make sure cleanup/shutdown works OK.
|
||
|
SCPUTS(_SC("Start Pass 1\n"));
|
||
|
doTest();
|
||
|
#if 0
|
||
|
SCPUTS(_SC("Start Pass 2\n"));
|
||
|
doTest();
|
||
|
#endif
|
||
|
SCPUTS(_SC("Done.\n"));
|
||
|
|
||
|
scprintf(_SC("Press RETURN to exit."));
|
||
|
getchar();
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|