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: 无法更改只读字符串
// ..

 

 源代码在这里:

ExpandedBlockStart.gif 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);
         if delegate ._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_

 

 

转载于:https://www.cnblogs.com/codezhang/archive/2010/09/09/1822246.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值