Hello QuickJS


#include "quickjs.h"
#include "quickjs-libc.h"
#include <string>
#include <iostream>
#include "cutils.h"

JSRuntime* QJSRuntime = nullptr;
JSContext* QJSContext = nullptr;

JSContext* CreateQJSContext(JSRuntime* InRuntime)
{
    JSContext* RetVal = JS_NewContext(QJSRuntime);
    js_init_module_std(RetVal, "std");
    js_init_module_os(RetVal, "os");
    return RetVal;
}

int InitQuickJSEnv()
{
	QJSRuntime = JS_NewRuntime();
	js_std_set_worker_new_context_func(CreateQJSContext);
	js_std_init_handlers(QJSRuntime);
	QJSContext = CreateQJSContext(QJSRuntime);
	JS_SetModuleLoaderFunc(QJSRuntime, nullptr, js_module_loader, nullptr);
	js_std_add_helpers(QJSContext, -1, nullptr);

    return 0;
}


struct MyClass
{
public:

    int VoidFunc()
    {
        std::cout<<"CppClass:VoidFunc()"<<std::endl;
    }

    static JSValue JSCtor(JSContext* InCtx, JSValueConst InNewTarget, int InArgc, JSValueConst* InArgv)
    {
        MyClass* data = nullptr;
        JSValue obj = JS_UNDEFINED;
        JSValue proto;

        data = (MyClass*)js_malloc(InCtx, sizeof(*data));

        if (InArgc > 0)
        {
            JS_ToInt32(InCtx, &data->IntVal, InArgv[0]);
        }

        proto = JS_GetPropertyStr(InCtx, InNewTarget, "prototype");
        obj = JS_NewObjectProtoClass(InCtx, proto, ClassID);
        JS_FreeValue(InCtx, proto);
        JS_SetOpaque(obj, data);

        return obj;
    }

    static JSValue JSGetIntVal(JSContext* InCtx, JSValueConst InThisVal, int InMagic)
    {
        MyClass* data = (MyClass*)JS_GetOpaque2(InCtx, InThisVal, ClassID);
        if (data == nullptr)
        {
            return JS_EXCEPTION;
        }

        return JS_NewInt32(InCtx, data->IntVal);
    }

    static JSValue JSSetIntVal(JSContext* InCtx, JSValueConst InThisVal, JSValue InValue, int InMagic)
    {
		MyClass* data = (MyClass*)JS_GetOpaque2(InCtx, InThisVal, ClassID);
		if (data == nullptr)
		{
			return JS_EXCEPTION;
		}

        int v = 0;
        JS_ToInt32(InCtx, &v, InValue);
        data->IntVal = v;

        return JS_UNDEFINED;
    }

    int IntVal = 0;

    static JSClassID ClassID;
    static JSClassDef ClassDef;
};

JSClassID MyClass::ClassID;
JSClassDef MyClass::ClassDef;


int ModuleInit(JSContext* InCtx, JSModuleDef* InModuleDef)
{

    JSValue JSMyClassProto, JSMyClass;

    JS_NewClassID(&MyClass::ClassID);

    MyClass::ClassDef.class_name = "MyClass";
    JS_NewClass(JS_GetRuntime(InCtx), MyClass::ClassID, &MyClass::ClassDef);

    JSMyClassProto = JS_NewObject(InCtx);

    JSCFunctionListEntry CppClassProtoFunc;
    CppClassProtoFunc.name = "IntVal";
    CppClassProtoFunc.prop_flags = JS_PROP_CONFIGURABLE;
    CppClassProtoFunc.def_type = JS_DEF_CGETSET;
    CppClassProtoFunc.magic = 0;
    CppClassProtoFunc.u.getset.get.getter_magic = &MyClass::JSGetIntVal;
    CppClassProtoFunc.u.getset.set.setter_magic = MyClass::JSSetIntVal;

    JS_SetPropertyFunctionList(InCtx, JSMyClassProto, &CppClassProtoFunc, 1);

    JSMyClass = JS_NewCFunction2(InCtx, MyClass::JSCtor, "MyClass", 1, JS_CFUNC_constructor, 0);

    JS_SetConstructor(InCtx, JSMyClass, JSMyClassProto);
    JS_SetClassProto(InCtx, MyClass::ClassID, JSMyClassProto);

    JS_SetModuleExport(InCtx, InModuleDef, "MyClass", JSMyClass);

    return 0;
}

int TestExportClassToJavaScript()
{
	JSModuleDef* m;
	m = JS_NewCModule(QJSContext, "CppModule", ModuleInit);
	if (!m)
		return -1;
	JS_AddModuleExport(QJSContext, m, "MyClass");

	char JSScript[] = R"(
        import * as CppModule from 'CppModule';
        var tmp = new CppModule.MyClass(12345);
        console.log(tmp.IntVal);
        tmp.IntVal = 123;
        console.log(tmp.IntVal);
        )";

    JSValue RetValue = JS_Eval(QJSContext, JSScript, strlen(JSScript), "", JS_EVAL_TYPE_MODULE);


    return 0;
}

int main(int argc,  char* argv[])
{
    InitQuickJSEnv();

    TestExportClassToJavaScript();

    js_std_dump_error(QJSContext);

    system("pause");
    return 0;
}





target('qjsc')
    set_kind('binary')
    add_defines('CONFIG_BIGNUM')
    add_defines('JS_STRICT_NAN_BOXING')
    add_files(
        'qjsc.c',
        'cutils.c',
        'quickjs.c',
        'quickjs-libc.c',
        'libunicode.c',
        'libregexp.c',
        'libbf.c',
        'repl.c'
    )

target('qjs')
    set_kind('binary')
    add_defines('CONFIG_BIGNUM')
    add_defines('JS_STRICT_NAN_BOXING')
    add_files(
        'qjs.c',
        'cutils.c',
        'quickjs.c',
        'quickjs-libc.c',
        'libunicode.c',
        'libregexp.c',
        'libbf.c',
        'repl.c',
        'qjscalc.c'
    )

target('JSPointModule')
    set_kind('shared')
    add_defines('CONFIG_BIGNUM')
    add_defines('JS_STRICT_NAN_BOXING')
    add_files(
        'examples/point.c',
        'cutils.c',
        'quickjs.c',
        'quickjs-libc.c',
        'libunicode.c',
        'libregexp.c',
        'libbf.c',
        'repl.c',
        'qjscalc.c'
    )

target('LearnQuickJS')
    set_kind('binary')
    add_rules("mode.release", "mode.debug")
    add_defines('CONFIG_BIGNUM')
    add_defines('JS_STRICT_NAN_BOXING')
    add_includedirs('./')
    add_files(
        'LearnQuickJS.cpp',
        'cutils.c',
        'quickjs.c',
        'quickjs-libc.c',
        'libunicode.c',
        'libregexp.c',
        'libbf.c'
    )

posted @ 2023-04-01 16:15  剑过不留痕残月分断魂  阅读(145)  评论(0编辑  收藏  举报