YetAnotherForum
Welcome Guest Search | Active Topics | Log In | Register

Instance comparision
Alex95
#1 Posted : Wednesday, April 12, 2017 7:04:44 AM(UTC)
Rank: Newbie

Groups: Registered
Joined: 3/26/2014(UTC)
Posts: 7
Location: HUngary

Thanks: 0 times
Was thanked: 0 time(s) in 0 post(s)
Hello,

In my application, I have C++ classes/objects (similar to standard Unknown interface). These things are visible in Squirrel, methods may be called, properties changed, etc. Everything is fine.

I've tried to compare variables of such classes in Squirrel. If two variables point to same C++ object, comparison returns false;

Squirrel code:
Code:
local _sheet0=layout.GetSheet(0);
local _sheet1=layout.GetSheet(0);
local test1= _sheet0==_sheet1;


test1 is always false, but variables point to same C++ Object.

I've added _cmp method - in C++, in the same way as _get and _set. But it is never called.

I've traced and found place of comparison.
Code:
bool SQVM::IsEqual(const SQObjectPtr &o1,const SQObjectPtr &o2,bool &res)
{
    if(type(o1) == type(o2)) {
        res = [h](_rawval(o1) == _rawval(o2));[/h]
    }
    else {
        if(sq_isnumeric(o1) && sq_isnumeric(o2)) {
            res = (tofloat(o1) == tofloat(o2));
        }
        else {
            res = false;
        }
    }
    return true;
}

But rawvals are different, they point to different SQInstance objects, while SQInstance._userpointer point to my Unknown object and they are same.
So I've changed IsEqual method:
Code:
        SQObjectType t=type(o1);
    if(t == type(o2)) {
        if(t==OT_INSTANCE)
        {
            SQInstance*i1=(SQInstance*)_rawval(o1);
            SQInstance*i2=(SQInstance*)_rawval(o1);
            return i1->_userpointer==i2->_userpointer;
        }

        res = (_rawval(o1) == _rawval(o2));
    }


Everything started to work. But my question is: Is this bug in Squirrel or am I doing something wrong?

I'm using the following helper function to create class instance:

Code:
bool CreateNativeClassInstance(HSQUIRRELVM v,const char *classname,SQUserPointer ud,SQRELEASEHOOK hook)
{
    if(!ud)
        return false;
    SQInteger oldtop = sq_gettop(v);
    sq_pushroottable(v);
    wchar_t ustr[MAX_PATH];
    atow(classname,ustr,MAX_PATH);
    sq_pushstring(v,ustr,-1);
    if(SQ_FAILED(sq_rawget(v,-2))){//sq_rawget,-2
        sq_settop(v,oldtop);
        return false;
    }
    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 the class
    if(SQ_FAILED(sq_setinstanceup(v,-1,ud))) {
        sq_settop(v,oldtop);
        return false;
    }
    sq_setreleasehook(v,-1,hook);
    return true;
};

Thanks for any help.
absence
#2 Posted : Thursday, April 13, 2017 7:00:55 PM(UTC)
Rank: Advanced Member

Groups: Registered
Joined: 8/23/2014(UTC)
Posts: 109
Man
Location: Northern Germany & Lincolnshire, U.K.

Thanks: 1 times
Was thanked: 10 time(s) in 10 post(s)
Presuming Layout.GetSheet() calls CreateNativeClassInstance, they ARE different instances. You actually are creating a new squirrel instance that is (coincidentally from a squirrel point of view) simply having the same user data/user pointer; but squirrel can not and must not care about user pointers, for pretty obvious reasons.
You should re-use the squirrel instance object and not "attach" a c++ instance to more than one object.


Or, to put it in other word:s You CREATE a squirrel instance and expect it to be the SAME like one you CREATED before (while it is only SIMILAR). Obviously that won't work properly ;-)
You should also think about the releashook and when it should delete your C++ instance. (In your example, the releasehook is called TWICE and the end of execution for the very same reason: For squirrel, there are two instances which "coincidentally" have the same userpointer stored)

Again in other words, think of the HSQOBJECT representing the instance as another c++ instance or struct having a pointer member to your c++ class (which pretty much is actually happening, btw):

class sheet ; //your sheet class
extern sheet* sheet1 ;

class foo {
public:
foo(void *p) : somepointer(p) {} ;
~foo() {};
private:
void *somepointer ;
}

foo *t1=new foo(sheet1) ;
foo *t2=new foo(sheet1) ;
//t1 == t2 will be false, obviously!

Alex95
#3 Posted : Sunday, April 16, 2017 6:34:52 PM(UTC)
Rank: Newbie

Groups: Registered
Joined: 3/26/2014(UTC)
Posts: 7
Location: HUngary

Thanks: 0 times
Was thanked: 0 time(s) in 0 post(s)
Thank you, this makes the picture clear.
Form another side, this looks like major change on my side :(

Thanks again!
Users browsing this topic
Guest
Forum Jump  
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.

Clean Slate theme by Jaben Cargman (Tiny Gecko)
Powered by YAF 1.9.4 | YAF © 2003-2010, Yet Another Forum.NET
This page was generated in 0.093 seconds.