Show Changes Show Changes
Edit Edit
Print Print
Recent Changes Recent Changes
Subscriptions Subscriptions
Lost and Found Lost and Found
Find References Find References
Rename Rename
Administration Page Administration Page
Topic Locks Topic Locks

Search

History

5/31/2011 3:38:11 AM
-173.16.151.55
4/27/2011 9:41:42 AM
-92.112.48.166
7/5/2007 6:48:36 AM
-220.211.116.217
5/30/2007 12:38:59 PM
-125.72.28.38
5/28/2007 6:49:52 AM
-69.136.148.27
List all versions List all versions

RSS feed for the SquirrelWiki namespace

Sq Plus Native Created Instances With Correct Ancestry
.

(Fixed at snapshot 07/01/07 kkawachi)

To expose the bug:

 #include <string>
 #include <sqplus.h>


 class Base 
 {
        public:
                Base() {}
                virtual ~Base() {}


                static void Bind()
                {
                        SqPlus::SQClassDef<Base>(_T("Base")).
                                func(&Base::GetBaseId,"getBaseId");
                }


                std::string GetBaseId() { return "Base"; }


 };


 DECLARE_INSTANCE_TYPE(Base);


 class Derived : public Base 
 {


        public:
                Derived() : Base() {}
                virtual ~Derived() {}


                static void Bind()
                {
                        SqPlus::SQClassDef<Derived>(_T("Derived"),_T("Base")).
                                staticFunc( &Derived::GetNativeCreated, "getNativeCreated" );
                                func( &Derived::GetDerivedId, "getDerivedId");
                }


                std::string GetDerivedId() { return "Derived"; }


                static Derived* GetNativeCreated() { return instance; }


      private:
                static Derived* instance;
 };


 Derived* Derived::instance = new Derived();


 DECLARE_INSTANCE_TYPE(Derived);


 int _tmain(int argc, _TCHAR* argv[])
 {
      printf("Initialize Squirrel\n");
      SquirrelVM::Init();
      printf("Binding classes to squirrel\n");
      Base::Bind();
      Derived::Bind();


      try
      {
                SquirrelObject script = SquirrelVM::CompileBuffer(_T(
                        " \
                                local shouldWork = Derived(); \
                                print(\"Base id is \" + shouldWork.getBaseId()); \
                                local shouldFail = shouldWork.getNativeCreated(); \
                                print(\"Base id is \" + shouldFail.getBaseId()); \
                        "
                ));


                SquirrelVM::RunScript(script);
        }
        catch(SquirrelError& error)
        {
                printf("Error: %s\n",std::string(error.desc).c_str());
        }
 }

To fix it:

In sqplus.h add this after #define SQ_ANCESTOR_CLASS_INDEX T("_ci")

 #define SQ_CLASS_HEIRARCHY_TABLE _T("__ch")


 inline void PopulateAncestry(HSQUIRRELVM v, SquirrelObject& instance, SQUserPointer up) {


        int oldtop = sq_gettop(v);
        SquirrelObject objectTable = SquirrelVM::CreateTable();
      instance.SetValue(SQ_CLASS_OBJECT_TABLE_NAME,objectTable);


        SquirrelObject root = SquirrelVM::GetRootTable();
        if (root.Exists(SQ_CLASS_HEIRARCHY_TABLE))
        {
                SquirrelObject classHeirarchyTable = root.GetValue(SQ_CLASS_HEIRARCHY_TABLE);
                SQUserPointer myTypeTag;
                if(instance.GetTypeTag(&myTypeTag))
                {
                        SquirrelObject classHierArray = classHeirarchyTable.GetValue(INT(size_t(myTypeTag)));
                        if(OT_ARRAY == classHierArray.GetType())
                        {
                                INT count = classHierArray.Len();
                                for (INT i=0; i < count; i++) {
                                        SquirrelObject so = classHierArray.GetValue(i);
                                        sq_pushobject(v,so.GetObjectHandle());
                                        SQUserPointer typeTag;
                                        sq_gettypetag(v,-1,&typeTag);
                                        objectTable.SetUserPointer(INT(size_t(typeTag)),up);
                                        sq_poptop(v); 
                                } // for
                        }
                }
        }
        sq_settop(v,oldtop);
 }

Replace the PostConstruct function with this

 template<typename T>
 inline int PostConstruct(HSQUIRRELVM v,T * newClass,SQRELEASEHOOK hook) {


 #ifdef SQ_USE_CLASS_INHERITANCE
  StackHandler sa(v);
  HSQOBJECT ho = sa.GetObjectHandle(1); // OT_INSTANCE
  SquirrelObject instance(ho);
  PopulateAncestry(v,instance,newClass);
 #endif


  sq_setinstanceup(v,1,newClass);
  sq_setreleasehook(v,1,hook);
  return 1;
 } // PostConstruct

replace the RegisterClassType function with

 template<typename T>
 inline SquirrelObject RegisterClassType(HSQUIRRELVM v,const SQChar * scriptClassName, const SQChar * baseScriptClassName=0) {
   int top = sq_gettop(v);
   SquirrelObject newClass;
   if (CreateClass(v,newClass,(SQUserPointer)ClassType<T>::type(),scriptClassName,baseScriptClassName)) {
        SquirrelVM::CreateFunction(newClass,&ConstructReleaseClass<T>::construct,_T("constructor"));


 #ifdef SQ_USE_CLASS_INHERITANCE


    // <NOTE> New member vars cannot be added to instances (OT_INSTANCE): additions must occur on the defining class (OT_CLASS), before any instances are instantiated.
    if (!newClass.Exists(SQ_CLASS_OBJECT_TABLE_NAME)) { // Will always get table from most-derived registered class.
      SquirrelObject objectTable = SquirrelVM::CreateTable();
      newClass.SetValue(SQ_CLASS_OBJECT_TABLE_NAME,objectTable); // Constructors must add their 'this' pointer indexed by type to this table. See PostConstruct() above.
                                                                 // 11/2/05: This table will behave as a static global for each instance unless overwritten during construction (see PostConstruct() above).
    } // if


        SquirrelObject root = SquirrelVM::GetRootTable();
        SquirrelObject classHeirarchyTable; 
        if (!root.Exists(SQ_CLASS_HEIRARCHY_TABLE))
        {
                classHeirarchyTable = SquirrelVM::CreateTable();
                root.SetValue(SQ_CLASS_HEIRARCHY_TABLE,classHeirarchyTable);
        }
        else
        {
                classHeirarchyTable = root.GetValue(SQ_CLASS_HEIRARCHY_TABLE);
        }


        if(0 != baseScriptClassName)
        {
                if(root.Exists(baseScriptClassName))
                {
                        SquirrelObject baseClass = root.GetValue(baseScriptClassName);
                        SQUserPointer baseType;
                        if(baseClass.GetTypeTag(&baseType))
                        {
                                SquirrelObject classHierArray = classHeirarchyTable.GetValue((INT(size_t(baseType))));
                                if(OT_ARRAY == classHierArray.GetType())
                                {
                                        SquirrelObject newArray = classHierArray.Clone();
                                        newArray.ArrayAppend(newClass);
                                        classHeirarchyTable.SetValue((INT(size_t(ClassType<T>::type()))),newArray);
                                }
                        }
                }
        }
        else
        {
                SquirrelObject newArray = SquirrelVM::CreateArray(0);
                newArray.ArrayAppend(newClass);
                classHeirarchyTable.SetValue((INT(size_t(ClassType<T>::type()))),newArray);
        }


 #endif
   } // if
   sq_settop(v,top);
   return newClass;
 } // RegisterClassType

In SquirrelBindingsUtils.h replace CreateNativeClassInstance with this

 BOOL CreateNativeClassInstance(HSQUIRRELVM v,const SQChar *classname,SQUserPointer ud,SQRELEASEHOOK hook)
 {
        int oldtop = sq_gettop(v);
        sq_pushroottable(v);
        sq_pushstring(v,classname,-1);
        if(SQ_FAILED(sq_rawget(v,-2))){ // Get the class (created with sq_newclass()).
                sq_settop(v,oldtop);
                return FALSE;
        }
        //sq_pushroottable(v);
        if(SQ_FAILED(sq_createinstance(v,-1))) {
                sq_settop(v,oldtop);
                return FALSE;
        }


 #ifdef SQ_USE_CLASS_INHERITANCE
        HSQOBJECT ho;
        sq_getstackobj(v,-1,&ho); // OT_INSTANCE
        SquirrelObject instance(ho);
        SqPlus::PopulateAncestry(v,instance,ud);
 #endif


        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;
 }
Not logged in. Log in

squirrel's community wiki

This is FlexWiki, an open source wiki engine.

Change Style

Recent Topics