![]() |
Show Changes |
![]() |
Edit |
![]() |
|
![]() |
Recent Changes |
![]() |
Subscriptions |
![]() |
Lost and Found |
![]() |
Find References |
![]() |
Rename |
![]() |
Administration Page |
![]() |
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 |
(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; }