quickjs icon indicating copy to clipboard operation
quickjs copied to clipboard

question about registering functions as callbacks for custom class?

Open mightgoyardstill opened this issue 2 years ago • 1 comments

i'm currently trying to embed quickjs into my own project where i have my own custom classes, i'm a little confused on how to set up a callback and cant for the life of me find any answers online. my current js script looks like this:

import { MyClass } from "MyClass"

let c = new MyClass();
c.addEventListener("callback", arbitraryFunctionName);

function otherFunction()
{
    print("update()");
}

function arbitraryFunctionName()
{
    print("function successfully called from main.cpp");
    otherFunction(); // when testing this didn't work because of scope?
}

i'm registering my callback functions into a std::map like so:

static JSValue myClass_addEventListener(
    JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
{
    std::cout << "CXX: myClass_addEventListener" << std::endl;

    auto* object = static_cast<MyClassData *>(JS_GetOpaque2(ctx, this_val, MyClassID));

    // Check if correct arguments are provided
    if (!object || argc != 2 || !JS_IsString(argv[0]) || !JS_IsFunction(ctx, argv[1])) 
        return JS_ThrowTypeError(ctx, "Expected a string and a function as arguments");

    // Convert the event type argument to a string
    const char* eventType = JS_ToCString(ctx, argv[0]);

    // Store the callback function in the object
    JSValue function = JS_DupValue(ctx, argv[1]);
    object->eventListeners[eventType] = function;

    // This does call the function but seg faults straight after, and not practical
    // would be good to call some sort of triggerEvent() function from main.cpp?
    // JSValue result = JS_Call(ctx, function, this_val, 0, nullptr);
    // JS_FreeValue(ctx, function);
    // JS_FreeValue(ctx, result);

    JS_FreeCString(ctx, eventType);

    return JS_UNDEFINED;
}

mightgoyardstill avatar May 16 '23 16:05 mightgoyardstill

this is evaluating it in my main.cpp, unfortunately if you don't use JS_EVAL_TYPE_MODULE you can't import modules as far as i'm aware?

        JSRuntime *runtime = JS_NewRuntime();
        JSContext *context = JS_NewContext(runtime);

        JSValue globaljs = JS_GetGlobalObject(context);
        JSValue jsPrint = JS_NewCFunction(context, jsPrintf, "print", 1);
        JS_SetPropertyStr(context, globaljs, "print", jsPrint);

        JS_FreeValue(context, globaljs);

        initMyModule(context, "MyClass");
        
        if (auto script = read_file("hello-world.js"); !script.empty())
        {
            JSValue val = JS_Eval(
                context, script.c_str(), script.length(), "hello-world.js", JS_EVAL_TYPE_MODULE);

            if (auto [error, error_message] = getJSError(context, val); error) 
                std::cerr << "JS Exception: " << error_message << std::endl;
            else
            {
                // trigger callbacks here...
            }
            JS_FreeValue(context, val);

mightgoyardstill avatar May 16 '23 16:05 mightgoyardstill