Squirrel 3.0beta 中绑定全局变量

Squirrel 2.x 对64位平台支持不是很好,转到3.0beta版却发现sqplus似乎不支持该版本,强行编译会出现若干问题。sqrat对3.0版支持较好,可能是本人的无知,不知如何对全局变量绑定,经过一上午的分析,从sqplus中分离出了变量绑定的代码,方便需要者使用。

使用方法:

//c++源文件中的代码

//包含头文件
#include "sqGlobalVariable.h"
//...

    
//绑定全局变量
    
//使用方法:
    
// BindVariable(VM,变量地址,绑定名称,[读写权限])
    int iVar = 777;
    std::
string sVar = "This is a string";
    
char *= "This is a const string";
    
float fVar  = 1.0E-50f;
    
double dVar = 1.0E-50;
    BindVariable(v,
&iVar,_SC("iVar")); //绑定一个整形变量
    BindVariable(v,&sVar,"sVar"); //绑定一个字符串变量
    BindVariable(v,&s,"s",VAR_ACCESS_READ_WRITE); //绑定一个只读字符串
    BindVariable(v,&fVar,"fVar"); //绑定一个float类型变量
    BindVariable(v,&dVar,"dVar"); //绑定一个double类型变量


//脚本文件中代码
print(iVar+1);//访问整形全局变量
print(sVar); //访问字符串
= "aaa"//error: 无法更改只读字符串
//..

 

 源代码在这里:

sqGlobalVariable.h
#ifndef _SQGLOBALVARIABLE_H_
#define _SQGLOBALVARIABLE_H_

#include 
<squirrel.h>
#include 
<string>

#if defined(_MSC_VER) || defined(__BORLANDC__) 
#include 
<tchar.h>
#ifndef UNICODE
#define SCSNPRINTF _snprintf
#define SCPUTS puts
#else
#define SCSNPRINTF _snwprintf
#define SCPUTS _putws
#endif
#else
#define _T(n) n
#define SCSNPRINTF snprintf
#include 
<stdio.h> // for snprintf
#define SCPUTS puts
#endif

typedef 
enum VarAccessType
{
    VAR_ACCESS_READ_WRITE
=0,
    VAR_ACCESS_READ_ONLY 
=1<<0,
    VAR_ACCESS_CONSTANT  
=1<<1,
    VAR_ACCESS_STATIC    
=1<<2
}VarAccessType;

typedef 
enum ScriptVarType
{
    VAR_TYPE_NONE
=-1,
    VAR_TYPE_CHAR,
    VAR_TYPE_INT,
    VAR_TYPE_FLOAT,
    VAR_TYPE_DOUBLE,
    VAR_TYPE_BOOL,
    VAR_TYPE_CONST_STRING,
    VAR_TYPE_STRING,
    VAR_TYPE_USER_POINTER,
    VAR_TYPE_INSTANCE
}ScriptVarType;

template 
<typename T>
struct TypeInfo {
    
const SQChar * typeName;
    
enum {TypeID=VAR_TYPE_NONE,Size=0};
};

// === Common Variable Types ===
template<>
struct TypeInfo<char> {
  
const SQChar * typeName;
  TypeInfo() : typeName(_T(
"char")) {}
  
enum {TypeID=VAR_TYPE_CHAR,Size=sizeof(char)};
  
operator ScriptVarType() { return ScriptVarType(TypeID); }
};
template
<>
struct TypeInfo<int> {
    
const SQChar * typeName;
    TypeInfo() : typeName(_T(
"int")) {}
    
enum {TypeID=VAR_TYPE_INT,Size=sizeof(int)};
    
operator ScriptVarType() { return ScriptVarType(TypeID); }
};
template
<>
struct TypeInfo<float> {
  
const SQChar * typeName;
  TypeInfo() : typeName(_T(
"float")) {}
  
enum {TypeID=VAR_TYPE_FLOAT,Size=sizeof(float)};
  
operator ScriptVarType() { return ScriptVarType(TypeID); }
};
template
<>
struct TypeInfo<double> {
    
const SQChar * typeName;
    TypeInfo() : typeName(_T(
"double")) {}
    
enum {TypeID=VAR_TYPE_DOUBLE,Size=sizeof(double)};
    
operator ScriptVarType() { return ScriptVarType(TypeID); }
};
template
<>
struct TypeInfo<bool> {
    
const SQChar * typeName;
    TypeInfo() : typeName(_T(
"bool")) {}
    
enum {TypeID=VAR_TYPE_BOOL,Size=sizeof(bool)};
    
operator ScriptVarType() { return ScriptVarType(TypeID); }
};
template
<>
struct TypeInfo<std::string> {
    
const SQChar * typeName;
    TypeInfo() : typeName(_T(
"string")) {}
    
enum {TypeID=VAR_TYPE_STRING,Size=sizeof(std::string)};
    
operator ScriptVarType() { return ScriptVarType(TypeID); }
};
template
<>
struct TypeInfo<SQUserPointer> {
    
const SQChar * typeName;
    TypeInfo() : typeName(_T(
"SQUserPointer")) {}
    
enum {TypeID=VAR_TYPE_USER_POINTER,Size=sizeof(SQUserPointer)};
    
operator ScriptVarType() { return ScriptVarType(TypeID); }
};
template
<>
struct TypeInfo<const SQChar *> {
    
const SQChar * typeName;
    TypeInfo() : typeName(_T(
"const SQChar *")) {}
    
enum {TypeID=VAR_TYPE_CONST_STRING,Size=sizeof(const SQChar *)};
    
operator ScriptVarType() { return ScriptVarType(TypeID); }
};

// See VarRef and ClassType<> below: for instance assignment.
typedef void (*CopyVarFunc)(void * dst,void * src);


// Internal use only.
inline void AttachToStackObject(HSQUIRRELVM vm,int idx,HSQOBJECT &so)
{
    HSQOBJECT t;
    sq_getstackobj(vm,idx,
&t);
    sq_addref(vm,
&t);
    sq_release(vm,
&so);
    so 
= t;
}
inline HSQOBJECT GetRootTable(HSQUIRRELVM vm)
{
    
static bool bInit = false;
    
static HSQOBJECT root;
    
if(!bInit){
        sq_resetobject(
&root); //new object
        AttachToStackObject(vm,-1,root);
        sq_pop(vm,
1);
        bInit 
= true;
    }
    
return root;
}
inline 
bool GetSlot(HSQUIRRELVM vm,const HSQOBJECT &so,const SQChar *name)
{
    sq_pushobject(vm,so);
    sq_pushstring(vm,name,
-1);
    
return SQ_SUCCEEDED(sq_get(vm,-2));// ? true : false;
}
inline HSQOBJECT GetValue(HSQUIRRELVM vm,
const HSQOBJECT &so,const SQChar *key)
{
    
//SquirrelObject ret;
    HSQOBJECT ret; sq_resetobject(&ret);
    
if(GetSlot(vm,so,key)) {
        AttachToStackObject(vm,
-1,ret);
        sq_pop(vm,
1);
    }
    sq_pop(vm,
1);
    
return ret;
}
bool SetValue(HSQUIRRELVM vm,const HSQOBJECT &so,const SQChar *key,const HSQOBJECT &val)
{
    
//_SETVALUE_STR_BEGIN
    bool ret = false;
    SQInteger top 
= sq_gettop(vm);
    sq_pushobject(vm,so);
    sq_pushstring(vm,key,
-1);

    sq_pushobject(vm,val);

    
//_SETVALUE_STR_END
    ret = SQ_SUCCEEDED(sq_rawset(vm,-3));
    sq_settop(vm,top);
    
return ret;
}
bool SetValue(HSQUIRRELVM vm,const HSQOBJECT &so,SQInteger key,const SQChar *s)
{
    
//_SETVALUE_INT_BEGIN
    bool ret = false;
    SQInteger top 
= sq_gettop(vm);
    sq_pushobject(vm,so);
    sq_pushinteger(vm,key);

    sq_pushstring(vm,s,
-1);

    
//_SETVALUE_INT_END
    ret = SQ_SUCCEEDED(sq_rawset(vm,-3));
    sq_settop(vm,top);
    
return ret;
}
inline HSQOBJECT CreateTable(HSQUIRRELVM vm)
{
    
//SquirrelObject ret;
    HSQOBJECT ret; sq_resetobject(&ret);
    sq_newtable(vm);
    AttachToStackObject(vm,
-1,ret);
    sq_pop(vm,
1);
    
return ret;
}

#define SQ_PLUS_TYPE_TABLE _T("__SqTypes")

struct VarRef
{
    
// In this case 'offsetOrAddrOrConst' is simpler than using an anonymous union.
    void * offsetOrAddrOrConst; // Instance member variable offset from 'this' pointer base (as size_t), or address if static variable (void *), or constant value.
    ScriptVarType type;         // Variable type (from enum above).
    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.
    CopyVarFunc copyFunc;       // Function pointer to copy variables (for instance variables only).
    short size;                 // Currently for debugging only (size of item when pointer to item is dereferenced). Could be used for variable max string buffer length.
    short access;               // VarAccessType.
    const SQChar * typeName;    // Type name string (to create instances by name).
    VarRef()
        :
        offsetOrAddrOrConst(
0),
        type(VAR_TYPE_NONE),
        instanceType((SQUserPointer)
-1),
        copyFunc(
0),
        size(
0),
        access(VAR_ACCESS_READ_WRITE)
        {}
    VarRef(
        HSQUIRRELVM vm,
        
const HSQOBJECT &so,
        
void * _offsetOrAddrOrConst,
        ScriptVarType _type,
        SQUserPointer _instanceType,
        CopyVarFunc _copyFunc,
        
int _size,
        VarAccessType _access,
        
const SQChar * _typeName
        )
        :offsetOrAddrOrConst(_offsetOrAddrOrConst), type(_type), instanceType(_instanceType), copyFunc(_copyFunc), size(_size), access(_access), typeName(_typeName)
    {
        
//SquirrelObject typeTable = SquirrelVM::GetRootTable().GetValue(SQ_PLUS_TYPE_TABLE);
        HSQOBJECT typeTable = GetValue(vm,so,SQ_PLUS_TYPE_TABLE);
        
        
if (sq_isnull(typeTable)) {
            
//typeTable = SquirrelVM::CreateTable();
            typeTable = CreateTable(vm);

            
//SquirrelObject root = SquirrelVM::GetRootTable();
            HSQOBJECT root = GetRootTable(vm);

            
//root.SetValue(SQ_PLUS_TYPE_TABLE,typeTable);
            SetValue(vm,root,SQ_PLUS_TYPE_TABLE,typeTable);
        } 
// if

        
//typeTable.SetValue(INT((size_t)copyFunc),typeName);
        SetValue(vm,typeTable,(SQInteger)copyFunc,typeName);
    }
};

typedef VarRef 
* VarRefPtr;

struct StackHandler {
    StackHandler(HSQUIRRELVM v) {
        _top 
= sq_gettop(v);
        
this->= v;
    }
    
char GetChar(int idx) {
        SQInteger x 
= SQInteger(0);
        
if(idx > 0 && idx <= _top) {
            sq_getinteger(v,idx,
&x);
        }
        
return char(x);
    }
    
float GetFloat(int idx) {
        SQFloat x 
= SQFloat(0);
        
if(idx > 0 && idx <= _top) {
            sq_getfloat(v,idx,
&x);
        }
        
return float(x);
    }
    
double GetDouble(int idx) {
        SQFloat x 
= SQFloat(0);
        
if(idx > 0 && idx <= _top) {
            sq_getfloat(v,idx,
&x);
        }
        
return double(x);
    }
    
int GetInt(int idx) {
        SQInteger x 
= 0;
        
if(idx > 0 && idx <= _top) {
            sq_getinteger(v,idx,
&x);
        }
        
return int(x);
    }
    HSQOBJECT GetObjectHandle(
int idx) {
        HSQOBJECT x;
        
if(idx > 0 && idx <= _top) {
            sq_resetobject(
&x);
            sq_getstackobj(v,idx,
&x);
        }
        
return x;
    }
    
const SQChar *GetString(int idx)
    {
        
const SQChar *= NULL;
        
if(idx > 0 && idx <= _top) {
            sq_getstring(v,idx,
&x);
        }
        
return x;
    }
    SQUserPointer GetUserPointer(
int idx)
    {
        SQUserPointer x 
= 0;
        
if(idx > 0 && idx <= _top) {
            sq_getuserpointer(v,idx,
&x);
        }
        
return x;
    }
    SQUserPointer GetInstanceUp(
int idx,SQUserPointer tag)
    {
        SQUserPointer self;
        
if(SQ_FAILED(sq_getinstanceup(v,idx,(SQUserPointer*)&self,tag)))
            
return NULL;
        
return self;
    }
    SQUserPointer GetUserData(
int idx,SQUserPointer tag=0)
    {
        SQUserPointer otag;
        SQUserPointer up;
        
if(idx > 0 && idx <= _top) {
            
if(SQ_SUCCEEDED(sq_getuserdata(v,idx,&up,&otag))) {
                
if(tag == otag)
                    
return up;
            }
        }
        
return NULL;
    }
    
bool GetBool(int idx)
    {
        SQBool ret;
        
if(idx > 0 && idx <= _top) {
            
if(SQ_SUCCEEDED(sq_getbool(v,idx,&ret)))
                
return ret!=0;
        }
        
return false;
    }
    
int GetType(int idx)
    {
        
if(idx > 0 && idx <= _top) {
            
return (int)sq_gettype(v,idx);
        }
        
return -1;
    }

    
int GetParamCount() {
        
return (int)_top;
    }
    SQInteger Return(
const SQChar *s)
    {
        sq_pushstring(v,s,
-1);
        
return 1;
    }
    SQInteger Return(
const std::string &s)
    {
        sq_pushstring(v,s.c_str(),
-1);
        
return 1;
    }
    SQInteger Return(
float f)
    {
        sq_pushfloat(v,SQFloat(f));
        
return 1;
    }
    SQInteger Return(
double d)
    {
        sq_pushfloat(v,SQFloat(d));
        
return 1;
    }
    SQInteger Return(
int i)
    {
        sq_pushinteger(v,SQInteger(i));
        
return 1;
    }
    SQInteger Return(
char c)
    {
        sq_pushinteger(v,SQInteger(c));
        
return 1;
    }
    SQInteger Return(
bool b)
    {
        sq_pushbool(v,SQBool(b));
        
return 1;
    }
    SQInteger Return(SQUserPointer p) {
        sq_pushuserpointer(v,p);
        
return 1;
    }
    SQInteger Return(HSQOBJECT 
&o)
    {
        sq_pushobject(v,o);
        
return 1;
    }
    SQInteger Return() { 
return 0; }
    SQInteger ThrowError(
const SQChar *error) {
        
return sq_throwerror(v,error);
    }
    HSQUIRRELVM GetVMPtr() { 
return v; }
private:
    SQInteger _top;
    HSQUIRRELVM v;
};

inline 
bool NewUserData(HSQUIRRELVM vm,const HSQOBJECT &so,const SQChar * key,unsigned size,SQUserPointer * typetag=0) {
    
//_SETVALUE_STR_BEGIN
    bool ret = false;
    SQInteger top 
= sq_gettop(vm);
    sq_pushobject(vm,so); \
    sq_pushstring(vm,key,
-1);

    sq_newuserdata(vm,size);
    
if (typetag) sq_settypetag(vm,-1,typetag);
    
    
//_SETVALUE_STR_END
    ret = SQ_SUCCEEDED(sq_rawset(vm,-3));
    sq_settop(vm,top);
    
return ret;
}
inline 
bool GetUserData(HSQUIRRELVM vm,const HSQOBJECT &so,const SQChar * key,SQUserPointer * data,SQUserPointer * typetag=0) {
    
bool ret = false;
    
if (GetSlot(vm,so,key)) {
        sq_getuserdata(vm,
-1,data,typetag);
        sq_pop(vm,
1);
        ret 
= true;
    } 
// if
    sq_pop(vm,1);
    
return ret;
}
inline 
void getVarNameTag(SQChar * buff,unsigned maxSize,const SQChar * scriptName) {
    
//  assert(maxSize > 3);
    SQChar * d = buff;
    d[
0= _SC('_');
    d[
1= _SC('v');
    d 
= &d[2];
    maxSize 
-= (2+1); // +1 = space for null.
    unsigned pos=0;
    
while (scriptName[pos] && pos < maxSize) {
        d[pos] 
= scriptName[pos];
        pos
++;
    } 
// while
    d[pos] = 0// null terminate.
}
HSQOBJECT CreateFunction(HSQUIRRELVM vm,SQFUNCTION func,
const SQChar * scriptFuncName,const SQChar * typeMask) {
    sq_pushstring(vm,scriptFuncName,
-1);
    sq_newclosure(vm,func,
0);

    HSQOBJECT ret; sq_resetobject(
&ret);
    AttachToStackObject(vm,
-1,ret);
    SQChar tm[
64];
    SQChar 
* ptm = tm;
    
int numParams = SQ_MATCHTYPEMASKSTRING;
    
if (typeMask) {
        
if (typeMask[0== _SC('*')) {
            ptm       
= 0// Variable args: don't check parameters.
            numParams = 0// Clear SQ_MATCHTYPEMASKSTRING (does not mean match 0 params. See sq_setparamscheck()).
        }
        
else {
            
if (SCSNPRINTF(tm,sizeof(tm),_SC("t|y|x%s"),typeMask) < 0) {
                
//throw _T("CreateFunction: typeMask string too long.");
                sq_throwerror(vm,_SC("CreateFunction: typeMask string too long."));
            }
        }
    }
    
else { // <TODO> Need to check object type on stack: table, class, instance, etc.
        SCSNPRINTF(tm,sizeof(tm),_SC("%s"),_SC("t|y|x")); // table, class, instance.
    }
#if 0
    sq_setparamscheck(_VM,numParams
+1,ptm); // Parameters are table+args (thus, the +1).
#else
    
if (ptm) {
        sq_setparamscheck(vm,numParams,ptm); 
// Determine arg count from type string.
    } // if
#endif

#ifdef _DEBUG
    sq_setnativeclosurename(vm,
-1,scriptFuncName); // For debugging only.
#endif
    sq_createslot(vm,
-3); // Create slot in table or class (assigning function to slot at scriptNameFunc).
    return ret;
}

inline VarRefPtr createVarRef(HSQUIRRELVM vm,
const HSQOBJECT &so,const SQChar * scriptVarName) {
    VarRefPtr pvr
=0;
    SQChar scriptVarTagName[
256];
    getVarNameTag(scriptVarTagName,
sizeof(scriptVarTagName),scriptVarName);
    
if (!GetUserData(vm,so,scriptVarTagName,(SQUserPointer *)&pvr)) {
        NewUserData(vm,so,scriptVarTagName,
sizeof(*pvr));
        
if (!GetUserData(vm,so,scriptVarTagName,(SQUserPointer *)&pvr)){
            
//throw _T("Could not create UserData.");
            sq_throwerror(vm,_SC("Could not create UserData."));
        }
    } 
// if
    return pvr;
}


bool RawGetSlot(HSQUIRRELVM vm,HSQOBJECT &so,const SQChar *name)
{
    sq_pushobject(vm,so);
    sq_pushstring(vm,name,
-1);
    
return SQ_SUCCEEDED(sq_rawget(vm,-2));
}
bool RawGetUserData(HSQUIRRELVM vm,HSQOBJECT &so,const SQChar * key,SQUserPointer * data,SQUserPointer * typetag=0) {
    
bool ret = RawGetSlot(vm,so,key);
    
if (ret) {
        sq_getuserdata(vm,
-1,data,typetag);
        sq_pop(vm,
1);
    }
    sq_pop(vm,
1);
    
return ret;
}
int getVarInfo(HSQUIRRELVM vm,StackHandler & sa,VarRefPtr & vr) {
    HSQOBJECT htable 
= sa.GetObjectHandle(1);

    
//SquirrelObject table(htable);
    sq_addref(vm,&htable);

#ifdef _DEBUG
    SQObjectType type 
= (SQObjectType)sa.GetType(2);
#endif

    
const SQChar * el = sa.GetString(2);
    
//ScriptStringVar256 varNameTag;
    SQChar varNameTag[256];
    getVarNameTag(varNameTag,
sizeof(varNameTag),el);
    SQUserPointer data
=0;

    
if (!RawGetUserData(vm,htable,varNameTag,&data)) {
        
//return sa.ThrowError(_T("getVarInfo: Could not retrieve UserData")); // Results in variable not being found error.
        sq_throwerror(vm,_SC("getVarInfo: Could not retrieve UserData"));
        
return SQ_ERROR;
    }
    vr 
= (VarRefPtr)data;
    
return SQ_OK;
}
bool CreateNativeClassInstance(HSQUIRRELVM v,const SQChar *classname,SQUserPointer ud,SQRELEASEHOOK hook)
{
    SQInteger oldtop 
= sq_gettop(v);
    sq_pushroottable(v);
    sq_pushstring(v,classname,
-1);

    
// Get the class (created with sq_newclass()).
    if(SQ_FAILED(sq_rawget(v,-2))){
        sq_settop(v,oldtop);
        
return false;
    }
    
//sq_pushroottable(v);
    if(SQ_FAILED(sq_createinstance(v,-1))) {
        sq_settop(v,oldtop);
        
return false;
    }
    sq_remove(v,
-3); //removes the root table
    sq_remove(v,-2); //removes the class
    if(SQ_FAILED(sq_setinstanceup(v,-1,ud))) {
        sq_settop(v,oldtop);
        
return false;
    }
    sq_setreleasehook(v,
-1,hook);
    
return true;
}
SQInteger setVar(StackHandler 
& sa,VarRef * vr,void * data) {
    SQChar msg[
256];
    
if (vr->access & (VAR_ACCESS_READ_ONLY|VAR_ACCESS_CONSTANT)) {
        
const SQChar * el = sa.GetString(2);
        SCSNPRINTF(msg,
sizeof(msg),_SC("setVar(): Cannot write to constant: %s"),el);
        
//throw msg;
        sq_throwerror(sa.GetVMPtr(),msg);
        
return SQ_ERROR;
    } 
// if

    
switch (vr->type) {
        
case TypeInfo<char>::TypeID: {
            
char * val = (char *)data; // Address
            if (val) {
                
*val = sa.GetChar(3);
                
return sa.Return(*val);
            } 
// if
            break;
        } 
// case
        case TypeInfo<int>::TypeID: {
            
int * val = (int *)data; // Address
            if (val) {
                
*val = sa.GetInt(3);
                
return sa.Return(*val);
            } 
// if
            break;
        } 
// case
        case TypeInfo<float>::TypeID: {
            
float * val = (float *)data; // Address
            if (val) {
                
*val = sa.GetFloat(3);
                
return sa.Return(*val);
            } 
// if
            break;
        } 
// case
        case TypeInfo<double>::TypeID: {
            
double * val = (double *)data; // Address
            if (val) {
                
*val = sa.GetFloat(3);
                
return sa.Return(*val);
            } 
// if
            break;
        } 
// case
        case TypeInfo<bool>::TypeID: {
            
bool * val = (bool *)data; // Address
            if (val) {
                
*val = sa.GetBool(3);
                
return sa.Return(*val);
            } 
// if
            break;
        } 
// case
        case TypeInfo<std::string>::TypeID: {
            std::
string * val = (std::string *)data; // Address
            if (val) {
                
const SQChar * strVal = sa.GetString(3);
                
*val = strVal;
                
return sa.Return(*val);
            } 
// if
            break;
        } 
// case
        case VAR_TYPE_INSTANCE: {
            HSQUIRRELVM v 
= sa.GetVMPtr();
            
// vr->copyFunc is the LHS variable type: the RHS var's type is ClassType<>::type() (both point to ClassType<>::copy()).
            
// src will be null if the LHS and RHS types don't match.
            SQUserPointer src = sa.GetInstanceUp(3,(SQUserPointer)vr->copyFunc); // Effectively performs: ClassType<>::type() == ClassType<>getCopyFunc().
            if (!src){
                
//throw _T("INSTANCE type assignment mismatch");
                sq_throwerror(sa.GetVMPtr(),_SC("INSTANCE type assignment mismatch"));
                
return SQ_ERROR;
            }
            vr
->copyFunc(data,src);
            
return 0;
        }
        
case TypeInfo<SQUserPointer>::TypeID: {
            
const SQChar * el = sa.GetString(2);
            SCSNPRINTF(msg,
sizeof(msg),_SC("setVar(): Cannot write to an SQUserPointer: %s"),el);
            
//throw msg;
            sq_throwerror(sa.GetVMPtr(),msg);
            
return SQ_ERROR;
        }
    } 
// switch
    return SQ_ERROR;
// setVar

SQInteger getVar(StackHandler 
& sa,VarRef * vr,void * data) {
    
switch (vr->type) {
        
case TypeInfo<char>::TypeID: {
            
if (!(vr->access & VAR_ACCESS_CONSTANT)) {
                
char * val = (char *)data; // Address
                if (val) {
                    
return sa.Return(*val);
                } 
// if
            }
            
else{
                
char * val = (char *)&data; // Constant value
                return sa.Return(*val);
            } 
// if
            break;
        } 
// case
        case TypeInfo<int>::TypeID: {
            
if (!(vr->access & VAR_ACCESS_CONSTANT)) {
                
int * val = (int *)data; // Address
                if (val) {
                    
return sa.Return(*val);
                } 
// if
            }
            
else{
                
int * val = (int *)&data; // Constant value
                return sa.Return(*val);
            } 
// if
            break;
        } 
// case
        case TypeInfo<float>::TypeID: {
            
if (!(vr->access & VAR_ACCESS_CONSTANT)) {
                
float * val = (float *)data; // Address
                if (val) {
                    
return sa.Return(*val);
                } 
// if
            }
            
else {
                
float * val = (float *)&data; // Constant value
                return sa.Return(*val);
            } 
// if
            break;
        } 
// case
        case TypeInfo<double>::TypeID: {
            
if (!(vr->access & VAR_ACCESS_CONSTANT)) {
                
double * val = (double *)data; // Address
                if (val) {
                    
return sa.Return(*val);
                } 
// if
            }
            
else {
                
double * val = (double *)&data; // Constant value
                return sa.Return(*val);
            } 
// if
            break;
        } 
// case
        case TypeInfo<bool>::TypeID: {
            
if (!(vr->access & VAR_ACCESS_CONSTANT)) {
                
bool * val = (bool *)data; // Address
                if (val) return sa.Return(*val);
            }
            
else {
                
bool * val = (bool *)&data; // Constant value
                return sa.Return(*val);
            } 
// if
            break;
        } 
// case
        case TypeInfo<std::string>::TypeID: {
            
if (!(vr->access & VAR_ACCESS_CONSTANT)) {
                std::
string * val = (std::string *)data; // Address
                if (val) {
                    
return sa.Return(*val);
                } 
// if
            }
            
else {
                std::
string * val = (std::string *)&data; // Constant value
                return sa.Return(*val);
            } 
// if
            break;
        } 
// case
        case VAR_TYPE_INSTANCE:
            
if (!CreateNativeClassInstance(sa.GetVMPtr(),vr->typeName,data,0)) { // data = address. Allocates memory.
                
//ScriptStringVar256 msg;
                SQChar msg[256= _SC("\0");
                SCSNPRINTF(msg,
sizeof(msg),_T("getVar(): Could not create instance: %s"),vr->typeName);
                
throw msg;
            } 
// if
            return 1;
        
case TypeInfo<SQUserPointer>::TypeID:
            
return sa.Return(data); // The address of member variable, not the variable itself.
        case TypeInfo<const SQChar *>::TypeID: {
            
if (!(vr->access & VAR_ACCESS_CONSTANT)) {
                
//throw _T("getVar(): Invalid type+access: 'const SQChar *' without VAR_ACCESS_CONSTANT");
                sq_throwerror(sa.GetVMPtr(),_SC("getVar(): Invalid type+access: 'const SQChar *' without VAR_ACCESS_CONSTANT"));
                
return SQ_ERROR;
            }
            
else {
                
const SQChar* sptr = *(SQChar**)data;
                
return sa.Return(sptr); // Address
            } // if
            break;
        } 
// case
    } // switch
    return SQ_ERROR;
// getVar

SQInteger setVarFunc(HSQUIRRELVM v) {
    StackHandler sa(v);
    
if (sa.GetType(1== OT_TABLE) {
        VarRefPtr vr;
        
int res = getVarInfo(v,sa,vr);
        
if (res != SQ_OK) return res;
        
return setVar(sa,vr,vr->offsetOrAddrOrConst);
    }
    
return SQ_ERROR;
}
SQInteger getVarFunc(HSQUIRRELVM v) {
    StackHandler sa(v);
    
if (sa.GetType(1== OT_TABLE) {
        VarRefPtr vr;
        
int res = getVarInfo(v,sa,vr);
        
if (res != SQ_OK) return res;
        
return getVar(sa,vr,vr->offsetOrAddrOrConst);
    }
    
return SQ_ERROR;
}
inline 
void createTableSetGetHandlers(HSQUIRRELVM vm,const HSQOBJECT &so) {
    
//SquirrelObject delegate = so.GetDelegate();
    HSQOBJECT delegate; sq_resetobject(&delegate);
    
if(so._type == OT_TABLE || so._type == OT_USERDATA){
        SQInteger top 
= sq_gettop(vm);
        sq_pushobject(vm,so);
        sq_getdelegate(vm,
-1);
        AttachToStackObject(vm,
-1,delegate);
        sq_settop(vm,top);
    }

    
bool bExists = GetSlot(vm,so,_SC("_set")); sq_pop(vm,1);
    
if (!bExists) {
        
//delegate = SquirrelVM::CreateTable();
        sq_newtable(vm);
        AttachToStackObject(vm,
-1,delegate);
        sq_pop(vm,
1);

        
//SquirrelVM::CreateFunction(delegate,(SQFUNCTION)setVarFunc,_T("_set"),_T("sn|b|s")); // String var name = number(int or float) or bool or string.
        sq_pushobject(vm,delegate); //==>PushObject()
        CreateFunction(vm,setVarFunc,_SC("_set"),_SC("sn|b|s"));
        sq_pop(vm,
1);

        
//SquirrelVM::CreateFunction(delegate,(SQFUNCTION)getVarFunc,_T("_get"),_T("s"));      // String var name.
        sq_pushobject(vm,delegate);
        CreateFunction(vm,getVarFunc,_SC(
"_get"),_SC("s"));
        sq_pop(vm,
1);

        
//so.SetDelegate(delegate);
        ifdelegate._type == OT_TABLE ||
            
delegate._type == OT_NULL) {
            
switch(so._type) {
                
case OT_USERDATA:
                
case OT_TABLE:
                    sq_pushobject(vm,so);
                    sq_pushobject(vm,
delegate);
                    sq_setdelegate(vm,
-2);
                    
break;
            }
        }
    } 
// if
// createTableSetGetHandlers


// === Class Type Helper class: returns a unique number for each class type ===

template
<typename T>
struct ClassType_t {
    
static SQUserPointer type(void) { return (SQUserPointer)&copy; }
    
static CopyVarFunc getCopyFunc(void) { return (CopyVarFunc)&copy; }
    
static void copy(T * dst,T * src) {
        
*dst = *src;
    } 
// copy
};

template
<typename T>
void BindVariable(HSQUIRRELVM vm,T * var,const SQChar * scriptVarName,VarAccessType access=VAR_ACCESS_READ_WRITE) {
    HSQOBJECT root 
= GetRootTable(vm);
    VarRefPtr pvr 
= createVarRef(vm,root,scriptVarName);
    
*pvr = VarRef(vm,root,var,TypeInfo<T>(),0,ClassType_t<T>::getCopyFunc(),sizeof(*var),access,TypeInfo<T>().typeName);
    createTableSetGetHandlers(vm,root);
// BindVariable

// special for const string
template<>
void BindVariable<char*>(HSQUIRRELVM vm,char ** var,const SQChar * scriptVarName, VarAccessType /*access*/) {
    HSQOBJECT root 
= GetRootTable(vm);
    VarRefPtr pvr 
= createVarRef(vm,root,scriptVarName);
    
*pvr = VarRef(vm,root,var,TypeInfo<const char*>(),0,ClassType_t<const char*>::getCopyFunc(),sizeof(*var),VAR_ACCESS_CONSTANT,TypeInfo<const char*>().typeName);
    createTableSetGetHandlers(vm,root);
// BindVariable

#endif //_SQGLOBALVARIABLE_H_

 

 

posted on 2010-09-09 13:49  codezhang  阅读(663)  评论(0编辑  收藏  举报

导航