Advertisement

Script handles & pointer retrieval through indirection

Started by October 02, 2018 10:47 PM
1 comment, last by MrFloat 6 years, 1 month ago

Hello,

For performance reasons, I'm using slot map container on C++ side to store instances of some particular object Foo. This means I'm not actually storing pointers to elements of that container directly because the whole access goes through special slot tables that map a key to an exact object instance - so instead of having Foo* registered for scripting as a usual refcounted reference there is one layer of indirection - I hold a "handle" that can be used to retrieve the pointer which will be valid for the time of the call. In C++ I would overload -> operator to hide this indirection, and still be able to use foo_handle->foo_method():


Foo* operator->() { 
  return slotmap.get(handle); 
} 

How can I register such handle on Angelscript side so I don't have to proxy all the methods to the actual retrieved Foo* instance? So instead of having this:


class FooScriptProxy
{
    FooHandle h;
    void addRef();   // refcounting the proxy
    void release();

    void fooMethodA() 
    {
       Foo* f = slot_map.get(h);
       if (f) f->fooMethodA();
       else 
          ??
    }

    void fooMethodB() 
    {
       Foo* f = slot_map.get(h);
       if (f) f->fooMethodB();
       else 
          ??
    }
}

I'd like to just be able to register the handle without delegating all the method calls manually while retrieving the pointer thru handle - so dynamically retrieved like through -> operator: So whenever I do something like this in script:


# C++ side:
class FooHandle
{
    SlotMapKey k; 
    Foo* retrieve() 
    {
        return slotmap.get(k);  // returns Foo* if exists in a map or nullptr if it wasn't found
    }

    void AddRef();
    void Release();
}

engine->RegisterObjectType("Foo", 0, asOBJ_REF)
engine->RegisterObjectBehaviour("Foo", asBEHAVE_ADDREF, "void f()", asMETHOD(FooHandle,AddRef), asCALL_THISCALL); assert( r >= 0 );
engine->RegisterObjectBehaviour("Foo", asBEHAVE_RELEASE, "void f()", asMETHOD(FooHandle,Release), asCALL_THISCALL); assert( r >= 0 );
-> here do some magic so it registers method "retrieve" in a way similar to arrow op?


# AS side:

Foo @foo = createFoo();
foo.fooMethodB();      # <---- when foo.method happens, it would mean Foo* f = FooHandle::retrieve; f.method()

it would actually dynamically retrieve the pointer, and then call method "fooMethodB" on it. 

Umm, hope it makes sense :D


Where are we and when are we and who are we?
How many people in how many places at how many times?

I don't think angelScript has an answer for your pursuit of convenience.

If you haven't checked some of the addon examples, weakref is an implementation of a value type handle that you might be interested if you don't actually need ref counting for your handles.

However it's fairly easy to automate a handle registration to simply have the same methods as the class you are interested in.
Given an angel script type info structure, you can loop through and register the same methods while also storing the original script function pointer in the new function user data. Provide all of the duplicate methods with the same function that just does the table lookup you want and uses the original function pointer from user data to call the actual function.

You should be able to automate the registration of a fake class/handle for any class this way.

This topic is closed to new replies.

Advertisement