![]() |
Show Changes |
![]() |
|
![]() |
Recent Changes |
![]() |
Subscriptions |
![]() |
Lost and Found |
![]() |
Find References |
![]() |
Rename |
![]() |
Administration Page |
![]() |
Topic Locks |
| Search |
History
| 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 |
| 7/13/2006 9:51:28 PM |
| -71.225.31.29 |
| 7/12/2006 12:04:48 PM |
| -71.224.62.52 |
![]() |
List all versions |
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")
inline void PopulateAncestry(HSQUIRRELVM v, SquirrelObject& instance, SQUserPointer up) {
SquirrelObject objectTable = SquirrelVM::CreateTable();
instance.SetValue(SQ_CLASS_OBJECT_TABLE_NAME,objectTable);
SquirrelObject classHierArray = instance.GetValue(SQ_CLASS_HIER_ARRAY);
INT heirarchyIndex = instance.GetValue(SQ_ANCESTOR_CLASS_INDEX).ToInteger();
INT count = classHierArray.Len();
if (heirarchyIndex < count)
{
for (INT i=0; i <= heirarchyIndex; 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
instance.SetValue(SQ_ANCESTOR_CLASS_INDEX,SquirrelObject()); // Store an OT_NULL object to free SQ_ANCESTOR_CLASS_INDEX var.
} // if
}
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
in the RegisterClassType function replace
classHierArray.ArrayAppend(newClass); // Add the class to the hierarchy array. The array values will be released and replaced with UserData to free created ancestor classes. newClass.SetValue(SQ_ANCESTOR_CLASS_INDEX,-1); // When the class hierarchy is created, this var will be used to help in recursively creating ancestor classes.
with
INT count = classHierArray.Len(); classHierArray.ArrayAppend(newClass); // Add the class to the hierarchy array. The array values will be released and replaced with UserData to free created ancestor classes. newClass.SetValue(SQ_ANCESTOR_CLASS_INDEX,count); // When the class hierarchy is created, this var will be used to help in recursively creating ancestor classes.
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;
}