Advertisement

Funcdef with template

Started by August 21, 2021 10:37 PM
4 comments, last by LeonMrBonnie 3 years, 3 months ago

Hello,

is it somehow possible to register a funcdef with a template argument?

For example, adding a method similiar to `Array.find` from JavaScript like this:

engine->RegisterFuncdef("bool FindCallback<T>(T&in item)");
engine->RegisterObjectMethod("array<T>", "T& find(FindCallback<T>@ callback) const", asFunctionPtr(ArrayFind), asCALL_CDECL_OBJFIRST);

The method posted does not work. Is it somehow possible to do something like that?
This would also be useful for e.g. a Promise class.

None

Yes, it is perfectly possible.

The array add-on already has a funcdef registered for sorting the array with a callback. You can easily do the same for a find routine using a callback.

	// Sort with callback for comparison
	r = engine->RegisterFuncdef("bool array<T>::less(const T&in if_handle_then_const a, const T&in if_handle_then_const b)");
	r = engine->RegisterObjectMethod("array<T>", "void sort(const less &in, uint startAt = 0, uint count = uint(-1))", asMETHODPR(CScriptArray, Sort, (asIScriptFunction*, asUINT, asUINT), void), asCALL_THISCALL); assert(r >= 0);

If you implement this and wish to share, I'd be happy to include it in the repository.

Regards,
Andreas

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

Advertisement

I tried but I get stuck.

Once the function where the .find was executed is done (stack is cleaned) my program crashes.

This is what I currently have:

static void* ArrayFind(CScriptArray* array, asIScriptFunction* callback)
{
    asIScriptEngine*  engine  = AngelScriptRuntime::Instance().GetEngine();
    asUINT            size    = array->GetSize();
    int               type    = array->GetElementTypeId();
    asIScriptContext* context = asGetActiveContext();
    void*             result  = nullptr;

    for(asUINT i = 0; i < size; i++)
    {
        auto item = array->At(i);
        context->PushState();
        int r = context->Prepare(callback);
        CHECK_AS_RETURN("Find callback prepare", r, NULL);
        r = context->SetArgAddress(0, item);
        CHECK_AS_RETURN("Find callback set item", r, NULL);
        r = context->SetArgDWord(1, i);
        CHECK_AS_RETURN("Find callback set index", r, NULL);
        r = context->Execute();
        CHECK_AS_RETURN("Find callback execute", r, NULL);
        bool callResult = context->GetReturnByte();
        context->Unprepare();
        context->PopState();
        if(callResult)
        {
            result = item;
            break;
        }
    }
    return result;
}

engine->RegisterFuncdef("bool array<T>::findCallback(const T&in if_handle_then_const item, const uint index)");
engine->RegisterObjectMethod("array<T>", "T& find(const findCallback&in callback) const", asFunctionPtr(ArrayFind), asCALL_CDECL_OBJFIRST);

I tried messing around with it but didn't fix it.

None

I don't see anything immediately wrong with your code. I would have to investigate it.

But, I recommend not push/popping the context callstack for each call. Do this just once for the entire loop.

Also, don't call Unprepare. This is not necessary as Execute/PopState would already do the necessary clean-up.

If I'd have to guess, I'd say the call to Unprepare may be what is causing the crash.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

You were right and the Unprepare was actually causing the crash. I also followed your advice of moving the stack pushing/popping out of the loop. I now have a working find implementation.

I actually realized that it might make more sense to add this to AngelScript itself, because currently I am just adding it in my own application. Will take a look to implementing that right into AngelScript and sending you a patch for it.

Thanks for the help!

None

This topic is closed to new replies.

Advertisement