Global Property Singleton

Started by
9 comments, last by WitchLord 9 years, 4 months ago

I'm having a similar problem as in this other post. But I'm not quite understanding how to fix this.

I have C++ objects I want to expose to the script as singletons of a particular class. I want these objects to be properties accessible to the script, but not be copyable or otherwise changed. These exposed object would have particular methods. These exposed objects would have application lifetime (they are created at the beginning and kept until the application exists).

For example, say I have this class in C++:


class MyClass
{
  public:
    MyClass(const std:string& n)
      : name(n)
    {
    }

    const std::string& get_name() const
    {
      return name;
    }

  private:
    const std::string name;
};

I want to expose several instances of MyClass to Angelscript as global properties. I register the class and method doing the following:


r = engine->RegisterObjectType("MyClass", 0, asOBJ_REF|asOBJ_NOCOUNT); assert(r >= 0);
  r = engine->RegisterObjectMethod("MyClass", "const string name() const", asMETHOD(MyClass, get_name), asCALL_THISCALL);  assert(r >= 0);

And then I create some instances and register them as global properties:


std::shared_ptr<MyClass> foo = std::make_shared<MyClass("foo");
std::shared_ptr<MyClass> bar = std::make_shared<MyClass("bar");

r = engine->RegisterGlobalProperty("MyClass foo", foo.get());  assert(r >= 0);
r = engine->RegisterGlobalProperty("MyClass bar", bar.get());  assert(r >= 0);

Then in Angelscript, whenever I try to invoke MyClass::get_name, 'this' is the wrong value. For example, stepping through with gdb, I get the following:

foo.get() = 0x82c6f0

bar.get() = 0x82cd60

And in Angelscript, if I do:


void main()
{
  string n = foo.name();
}

And setting a breakpoint in MyClass::get_name, 'this' is 0x82fd38, which is clearly something on the heap (perhaps something allocated by AS?).

I tried to follow the examples from other posts on singletons, such as this and this. But it doesn't seem to be working.

I'm using Angelscript 2.29.2.

Advertisement

I also tried using a wrapper:


static
const std::string& get_name_wrapper(MyClass *p)
{
  return p->get_name();
}

And registering it with asCALL_CDECL_OBJLAST:


r = engine->RegisterObjectMethod("MyClass", "const string name() const", asFUNCTION(get_name_wrapper), asCALL_CDECL_OBJLAST); assert(r >= 0);

And when I get into get_name_wrapper, 'p' has the same incorrect value.

(I've also tried some other flags when registering the class, such as asOBJ_NOHANDLE, but I get the same results).

I register mine through


MYASSERT(e->RegisterObjectType("Mouse", sizeof(Mouse), asOBJ_VALUE | asOBJ_POD) >= 0);
MYASSERT(e->RegisterGlobalProperty("Mouse Ms", &Ms) >= 0);

I register mine through

MYASSERT(e->RegisterObjectType("Mouse", sizeof(Mouse), asOBJ_VALUE | asOBJ_POD) >= 0);

MYASSERT(e->RegisterGlobalProperty("Mouse Ms", &Ms) >= 0);

And you create the 'Mouse' object as a simple object, or as a pointer? That is, do you do:

Mouse *Ms = new Mouse();

or

Mouse Ms();

The issue, I think, isn't the object itself, but what is passed to the methods. How do you register your methods

Doesn't happen anything different if I do either one of those the only thing that differs is registering with (reference)&Ms or (pointer)Ms


MYASSERT(e->RegisterObjectMethod("Mouse", "const Vector2 &pos()const", asMETHOD(Mouse, pos), asCALL_THISCALL) >= 0);

r = engine->RegisterObjectMethod("MyClass", "const string name() const", asMETHOD(MyClass, get_name), asCALL_THISCALL); assert(r >= 0);

shouldn't this be


r = engine->RegisterObjectMethod("MyClass", "const string &name() const", asMETHOD(MyClass, get_name), asCALL_THISCALL); assert(r >= 0);

like in your C++ class?

I did some more experiments. It doesn't matter what I pass as a pointer to RegisterGlobalProperty(), I get the exact same thing for 'this' (or 'p' in the wrapper). For example:


engine->RegisterGlobalProperty("MyClass foo", (void *)0xdeadbeef);

When I get into get_name (or get_name_wrapper), 'this' or 'p' is still something on the heap, NOT 0xdeadbeef.

r = engine->RegisterObjectMethod("MyClass", "const string name() const", asMETHOD(MyClass, get_name), asCALL_THISCALL); assert(r >= 0);

shouldn't this be

r = engine->RegisterObjectMethod("MyClass", "const string &name() const", asMETHOD(MyClass, get_name), asCALL_THISCALL); assert(r >= 0);

like in your C++ class?

Huh! That simple change did it.

Thank you Zervoke! Great catch. I just wish these kind of things didn't lead to segfaults....

This topic is closed to new replies.

Advertisement