Squirrel

The programming language
Welcome to Squirrel Sign in | Join | Help
in Search

[SqPlus] embed a smart pointer [Solved]

Last post 08-24-2007, 5:25 AM by m0pey. 6 replies.
Sort Posts: Previous Next
  •  07-31-2007, 6:49 AM 1982

    [SqPlus] embed a smart pointer [Solved]

    If i have a smart pointer class that looks like:

        class Pointee {
            int var;
            void func();
        };

        class SmartPointer {
        public:
           Pointee* operator ->();
        private:
           Pointee* p;
        };


    Is there anyway of binding the class SmartPointer with a function func() that calls the Pointee's func() using SqPlus? So in squirrel I would have:

    local pointer = SmartPointer();
    pointer.func();

    which is the C++ equivilent of:

    SmartPointer pointer;
    pointer->func();

    I've been looking around for awhile and can see how to do it using the DXSquirrel way of binding but just wondering if using that method conflicts with the SqPlus way of binding? Also the SqPlus method is much cleaner so i'd prefer todo it like that.
    Cheers,
    James
  •  07-31-2007, 4:56 PM 1991 in reply to 1982

    Re: [SqPlus] embed a smart pointer

    Sort of had a bash at hacking SqPlus so it works now with no bugs as of yet.
    Now works like this...

        class Pointee {
            int var;
            void func();
        };

        class SmartPointer {
            Pointee* operator -> () {
               return pPointee;
            }
       
            Pointee* pPointee;
        }

        SqClassDef<SmartPointer>("SmartPointer")
            .smartFunc<Pointee>(&Pointee::func, "func")
            .smartVar<Pointee>(&Pointee::var, "var");

    It assumes that you've overloaded the -> operator which is easy to change if you haven't and you also have to implement one func to get the offset to actual class data not the smart pointer for use in getInstanceVarInfo() in SqPlus.cpp which is:

        unsigned char* getSmartPointerPointee(unsigned char*);

    In the example above you'd do this like:

        unsigned char* getSmartPointerPointee(unsigned char* ptr) {
            return reinterpret_cast<unsigned char*>(reinterpret_cast<SmartPointer*>(ptr)->pPointee);
        }

    If anyone's interested I'll post up how I did it. Also I don't like the name Pointee so if anyone has a better name feel free to suggest.
    Cheers,
    James


  •  08-05-2007, 3:56 AM 2016 in reply to 1991

    Re: [SqPlus] embed a smart pointer

    Great job, James!
    Could you post the code for smart pointers?

    If you send me your Sourceforge account info by PM,
    I can add you as a developer of sqplus at sourceforge
    for merging your works to SVN by yourself.

    Regards,
    Kawachi
  •  08-05-2007, 3:14 PM 2019 in reply to 2016

    Re: [SqPlus] embed a smart pointer

    I copied the way that the const stuff was added in so if you add a file called SqPlusSmartPointer.h

    #ifdef SQPLUS_SMARTPOINTER_ACCESSTYPE
    #undef SQPLUS_SMARTPOINTER_ACCESSTYPE
    enum VarAccessType {VAR_ACCESS_READ_WRITE=0,VAR_ACCESS_READ_ONLY=1<<0,VAR_ACCESS_CONSTANT=1<<1,VAR_ACCESS_STATIC=1<<2,VAR_ACCESS_SMARTPOINTER=1<<3};
    #endif // #ifdef SQPLUS_SMARTPOINTER_ACCESSTYPE

    #ifdef SQPLUS_SMARTPOINTER_REGISTER_VARIABLE
    #undef SQPLUS_SMARTPOINTER_REGISTER_VARIABLE
    // classType is the type of the member variable's containing class.
    template<typename T>
    void RegisterSmartInstanceVariable(SquirrelObject & so,SQUserPointer classType,T * var,const SQChar * scriptVarName,VarAccessType access=VAR_ACCESS_READ_WRITE) {
        VarRef * pvr = createVarRef(so,scriptVarName);
        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.
        *pvr = VarRef(offsetOrAddrOrConst,TypeInfo<T>(),classType,ClassType<T>::getCopyFunc(),sizeof(*var),access,TypeInfo<T>().typeName);
        pvr->access |= VAR_ACCESS_SMARTPOINTER;
        createInstanceSetGetHandlers(so);
    } // RegisterInstanceVariable
    #endif // #ifdef SQPLUS_SMARTPOINTER_REGISTER_VARIABLE

    #ifdef SQPLUS_SMARTPOINTER_DISPATCH
    #undef SQPLUS_SMARTPOINTER_DISPATCH
    template<typename Callee,typename Pointee,typename Func>
    class DirectCallSmartInstanceMemberFunction {
    public:
      static inline int Dispatch(HSQUIRRELVM v) {
        StackHandler sa(v);
        Callee * instance = (Callee *)sa.GetInstanceUp(1,0);
        int paramCount = sa.GetParamCount();
        Func * func = (Func *)sa.GetUserData(paramCount);
    #ifdef SQ_USE_CLASS_INHERITANCE
        SquirrelObject so(sa.GetObjectHandle(1)); // 'this'
        SQUserPointer typetag; so.GetTypeTag(&typetag);
        SQUserPointer calleeType = ClassType<Callee>::type();
        if (typetag != calleeType) {
          SquirrelObject typeTable = so.GetValue(SQ_CLASS_OBJECT_TABLE_NAME);
          instance = (Callee *)typeTable.GetUserPointer(INT((size_t)ClassType<Callee>::type())); // <TODO> 64-bit compatible version.
          if (!instance) {
            return sq_throwerror(v,_T("Invalid Instance Type"));
          } // if
        } // if
    #endif
        Pointee * pointeeInstance = static_cast<Pointee*>(instance->get());
        if(!pointeeInstance) {
            return sq_throwerror(v,_T("SmartPointer Pointee NULL"));
        }
        return Call(*pointeeInstance,*func,v,2);
      } // Dispatch
    };
    #endif // #ifdef SQPLUS_SMARTPOINTER_DISPATCH

    #ifdef SQPLUS_SMARTPOINTER_DIRECT_CLOSURE
    #undef SQPLUS_SMARTPOINTER_DIRECT_CLOSURE

    template<typename Callee,typename Pointee,typename Func>
    inline void sq_pushdirectsmartinstanceclosure(HSQUIRRELVM v,const Callee & callee,const Pointee & pointee,Func func,SQUnsignedInteger nupvalues) {
      unsigned char * up = (unsigned char *)sq_newuserdata(v,sizeof(func));  // Also pushed on stack.
      memcpy(up,&func,sizeof(func));
      sq_newclosure(v,DirectCallSmartInstanceMemberFunction<Callee,Pointee,Func>::Dispatch,nupvalues+1);
    } // sq_pushdirectinstanceclosure

    #endif // #ifdef SQPLUS_SMARTPOINTER_DIRECT_CLOSURE

    #ifdef SQPLUS_SMARTPOINTER_REGISTER_INSTANCE
    #undef SQPLUS_SMARTPOINTER_REGISTER_INSTANCE

    template<typename Callee, typename Pointee, typename Func>
    inline void RegisterSmartInstance(HSQUIRRELVM v,HSQOBJECT hclass,Callee & callee,Pointee & pointee,Func func,const SQChar * name) {
      sq_pushobject(v,hclass);
      sq_pushstring(v,name,-1);
      sq_pushdirectsmartinstanceclosure(v,callee,pointee,func,0);
      sq_createslot(v,-3);
      sq_poptop(v); // Remove hclass.
    } // RegisterInstance

    #endif // #ifdef SQPLUS_SMARTPOINTER_REGISTER_INSTANCE


    #ifdef SQPLUS_SMARTPOINTER_CLASS_DEF
    #undef SQPLUS_SMARTPOINTER_CLASS_DEF

      // Register a smartpointer member function.
      template<typename Pointee, typename Func>
      SQClassDefBase & smartFunc(Func pfunc,const SQChar * name) {
        RegisterSmartInstance(v,newClass.GetObjectHandle(),*(TClassType *)0,*(Pointee *)0,pfunc,name);
        return *this;
      } // func

      // Register a member variable.
      template<typename Pointee, typename VarType>
      SQClassDefBase & smartVar(VarType Pointee::* pvar,const SQChar * name,VarAccessType access=VAR_ACCESS_READ_WRITE) {
          struct CV {
              VarType Pointee::* var;
          } cv; // Cast Variable helper.
          cv.var = pvar;
          RegisterSmartInstanceVariable(newClass,ClassType<TClassType>::type(),*(VarType **)&cv,name,access);
          return *this;
      } // var

      // Register a member variable as a UserPointer (read only).
      template<typename Pointee, typename VarType>
      SQClassDefBase & smartVarAsUserPointer(VarType Pointee::* pvar,const SQChar * name) {
          struct CV {
              VarType Pointee::* var;
          } cv; // Cast Variable helper.
          cv.var = pvar;
          RegisterSmartInstanceVariable(newClass,ClassType<TClassType>::type(),*(SQAnything **)&cv,name,VAR_ACCESS_READ_ONLY);
          return *this;
      } // varAsUserPointer

    #endif // #ifdef SQPLUS_SMARTPOINTER_CLASS_DEF


    #ifdef SQPLUS_SMARTPOINTER_CPP_DECLARATION
    #undef SQPLUS_SMARTPOINTER_CPP_DECLARATION
    extern unsigned char* getSmartPointerPointee(unsigned char*);
    #endif

    #ifdef SQPLUS_SMARTPOINTER_INSTANCE_VARINFO
    #undef SQPLUS_SMARTPOINTER_INSTANCE_VARINFO
        if(vr->access & VAR_ACCESS_SMARTPOINTER) {
            up = getSmartPointerPointee(up);
        }
    #endif // #ifdef SQPLUS_SMARTPOINTER_CPP_DECLARATION


    In SqPlus.cpp at line 4 you need to add:

    #ifdef SQPLUS_SUPPORT_SMART_POINTER
    #define SQPLUS_SMARTPOINTER_CPP_DECLARATION
    #include "SqPlusSmartPointer.h"
    #endif

    Then at line 60 add:

    #ifdef SQPLUS_SUPPORT_SMART_POINTER
    #define SQPLUS_SMARTPOINTER_INSTANCE_VARINFO
    #include "SqPlusSmartPointer.h"
    #endif


    In SqPlus.h there are quite a few additions but not major ones which are:

    line 78:

    // === Uncomment to support smart pointer ===
    #define SQPLUS_SUPPORT_SMART_POINTER

    line 276:

    #ifdef SQPLUS_SUPPORT_SMART_POINTER
    #define SQPLUS_SMARTPOINTER_ACCESSTYPE
    #include "SqPlusSmartPointer.h"
    #else
    enum VarAccessType {VAR_ACCESS_READ_WRITE=0,VAR_ACCESS_READ_ONLY=1<<0,VAR_ACCESS_CONSTANT=1<<1,VAR_ACCESS_STATIC=1<<2};
    #endif

    line 438:

    #ifdef SQPLUS_SUPPORT_SMART_POINTER
    #define SQPLUS_SMARTPOINTER_REGISTER_VARIABLE
    #include "SqPlusSmartPointer.h"
    #endif

    line 1231:

    #ifdef SQPLUS_SUPPORT_SMART_POINTER
    #define SQPLUS_SMARTPOINTER_DISPATCH
    #include "SqPlusSmartPointer.h"
    #endif

    and finally line 1295:

    #ifdef SQPLUS_SUPPORT_SMART_POINTER
    #define SQPLUS_SMARTPOINTER_DIRECT_CLOSURE
    #include "SqPlusSmartPointer.h"
    #endif


    I think thats all but if that doesn't work I'll send you the files I've got. Doesn't handle constants or variable argument functions but they're pretty easy to add if needed. I don't actually have a sourceforge account at the mo but I'll set one up and send you the details.
    Cheers,
    James
  •  08-08-2007, 8:25 AM 2035 in reply to 2019

    Re: [SqPlus] embed a smart pointer

    This is cool.
  •  08-10-2007, 3:17 AM 2044 in reply to 2035

    Re: [SqPlus] embed a smart pointer

    Thanks.
  •  08-24-2007, 5:25 AM 2101 in reply to 2044

    Re: [SqPlus] embed a smart pointer

    There's now a branch with it in at /branches/mopey-r73-smartpointer
View as RSS news feed in XML
Powered by Community Server, by Telligent Systems