enable constructor generation

This commit is contained in:
Alexander Klingenbeck 2023-05-09 23:25:28 +02:00
parent 68fb97127c
commit b48568aa87
7 changed files with 79 additions and 15 deletions

View File

@ -14,12 +14,15 @@ function main(){
g: { get: true, set: true },
b: { get: true, set: true },
a: { get: true, set: true },
}
},
createConstructor: true
})
core_gen.addApiFunctionByName("SetWindowTitle")
core_gen.addApiFunctionByName("SetWindowPosition")
core_gen.addApiFunctionByName("BeginDrawing")
core_gen.addApiFunctionByName("EndDrawing")
core_gen.addApiFunctionByName("ClearBackground")
core_gen.addApiFunctionByName("DrawText")
core_gen.writeTo("src/bindings/js_raylib_core.h")
const texture_gen = new RayLibHeader("raylib_texture", apiDesc)

View File

@ -1,6 +1,6 @@
import { writeFileSync } from "fs";
import { ApiFunction } from "./api"
import { CodeGenerator, CodeWriter, GenericCodeGenerator } from "./generation"
import { CodeGenerator, CodeWriter, FunctionArgument, GenericCodeGenerator } from "./generation"
export type StructLookup = { [struct: string]: string }
@ -109,10 +109,6 @@ export abstract class GenericQuickJsGenerator<T extends QuickJsGenerator> extend
}
}
jsConstructStruct(structName: string){
}
jsStructToOpq(structType: string, jsVar: string, srcVar: string, classId: string){
this.declare("ptr", structType+"*", false, `(${structType}*)js_malloc(ctx, sizeof(${structType}))`)
this.statement("*ptr = " + srcVar)
@ -210,6 +206,19 @@ export abstract class GenericQuickJsGenerator<T extends QuickJsGenerator> extend
fun.returnExp("JS_UNDEFINED")
return fun
}
jsStructConstructor(structName: string, fields: FunctionArgument[], classId: string){
const body = this.jsBindingFunction(structName + "_constructor")
for (let i = 0; i < fields.length; i++) {
const para = fields[i]
body.jsToC(para.type,para.name,"argv["+i+"]")
}
body.statement(`${structName} _struct = { ${fields.map(x => x.name).join(', ')} }`)
body.jsStructToOpq(structName,"_return","_struct", classId)
body.returnExp("_return")
return body
}
}
export class QuickJsGenerator extends GenericQuickJsGenerator<QuickJsGenerator> {

View File

@ -6,13 +6,12 @@ export interface StructBindingOptions {
properties?: { [key:string]: { get?:boolean, set?:boolean } },
destructor?: string,
construct?: string,
createConstructor?: boolean
}
export class RayLibHeader extends QuickJsHeader {
constructor(name: string, private api: ApiDescription){
super(name)
this.includes.include("raylib.h")
@ -76,7 +75,15 @@ export class RayLibHeader extends QuickJsHeader {
const classDecl = this.structs.jsClassDeclaration(struct.name, classId, finalizer.getTag("_name"), classFuncList.getTag("_name"))
this.moduleInit.call(classDecl.getTag("_name"), ["ctx", "m"])
// OPT: 7. expose class and constructor
if(options?.createConstructor){
const body = this.functions.jsStructConstructor(struct.name, struct.fields, classId)
this.moduleInit.statement(`JSValue ${struct.name}_constr = JS_NewCFunction2(ctx, ${body.getTag("_name")},"${struct.name})", ${struct.fields.length}, JS_CFUNC_constructor_or_func, 0)`)
this.moduleInit.call("JS_SetModuleExport", ["ctx","m", `"${struct.name}"`, struct.name+"_constr"])
this.moduleEntry.call("JS_AddModuleExport", ["ctx","m",'"'+struct.name+'"'])
}
}
addApiStructByName(structName: string, options?: StructBindingOptions){

View File

@ -368,8 +368,6 @@ class GenericQuickJsGenerator extends generation_1.GenericCodeGenerator {
this.jsStructToOpq(type, name, src, classId);
}
}
jsConstructStruct(structName) {
}
jsStructToOpq(structType, jsVar, srcVar, classId) {
this.declare("ptr", structType + "*", false, `(${structType}*)js_malloc(ctx, sizeof(${structType}))`);
this.statement("*ptr = " + srcVar);
@ -458,6 +456,17 @@ class GenericQuickJsGenerator extends generation_1.GenericCodeGenerator {
fun.returnExp("JS_UNDEFINED");
return fun;
}
jsStructConstructor(structName, fields, classId) {
const body = this.jsBindingFunction(structName + "_constructor");
for (let i = 0; i < fields.length; i++) {
const para = fields[i];
body.jsToC(para.type, para.name, "argv[" + i + "]");
}
body.statement(`${structName} _struct = { ${fields.map(x => x.name).join(', ')} }`);
body.jsStructToOpq(structName, "_return", "_struct", classId);
body.returnExp("_return");
return body;
}
}
exports.GenericQuickJsGenerator = GenericQuickJsGenerator;
class QuickJsGenerator extends GenericQuickJsGenerator {
@ -542,7 +551,12 @@ class RayLibHeader extends quickjs_1.QuickJsHeader {
classFuncList.jsPropStringDef("[Symbol.toStringTag]", struct.name);
const classDecl = this.structs.jsClassDeclaration(struct.name, classId, finalizer.getTag("_name"), classFuncList.getTag("_name"));
this.moduleInit.call(classDecl.getTag("_name"), ["ctx", "m"]);
// OPT: 7. expose class and constructor
if (options?.createConstructor) {
const body = this.functions.jsStructConstructor(struct.name, struct.fields, classId);
this.moduleInit.statement(`JSValue ${struct.name}_constr = JS_NewCFunction2(ctx, ${body.getTag("_name")},"${struct.name})", ${struct.fields.length}, JS_CFUNC_constructor_or_func, 0)`);
this.moduleInit.call("JS_SetModuleExport", ["ctx", "m", `"${struct.name}"`, struct.name + "_constr"]);
this.moduleEntry.call("JS_AddModuleExport", ["ctx", "m", '"' + struct.name + '"']);
}
}
addApiStructByName(structName, options) {
const struct = this.api.getStruct(structName);
@ -621,12 +635,15 @@ function main() {
g: { get: true, set: true },
b: { get: true, set: true },
a: { get: true, set: true },
}
},
createConstructor: true
});
core_gen.addApiFunctionByName("SetWindowTitle");
core_gen.addApiFunctionByName("SetWindowPosition");
core_gen.addApiFunctionByName("BeginDrawing");
core_gen.addApiFunctionByName("EndDrawing");
core_gen.addApiFunctionByName("ClearBackground");
core_gen.addApiFunctionByName("DrawText");
core_gen.writeTo("src/bindings/js_raylib_core.h");
const texture_gen = new raylib_header_1.RayLibHeader("raylib_texture", apiDesc);
texture_gen.addApiStructByName("Image", {

View File

@ -1,4 +1,4 @@
import { setWindowTitle, setWindowPosition } from "raylib.core"
import { setWindowTitle, setWindowPosition, Color } from "raylib.core"
import { loadImage } from "raylib.texture"
import { gc } from "std"
@ -9,6 +9,10 @@ console.log(img.width)
gc()
const color = new Color(1,2,3,4)
color.r = 10
console.log(color.r,color.g,color.b,color.a, color)
setWindowTitle("My Window")
setWindowPosition(20,50)

View File

@ -128,6 +128,27 @@ static int js_declare_Color(JSContext * ctx, JSModuleDef * m) {
return 0;
}
static JSValue js_Color_constructor(JSContext * ctx, JSValueConst this_val, int argc, JSValueConst * argv) {
int _int_r;
JS_ToInt32(ctx, &_int_r, argv[0]);
unsigned char r = (unsigned char)_int_r;
int _int_g;
JS_ToInt32(ctx, &_int_g, argv[1]);
unsigned char g = (unsigned char)_int_g;
int _int_b;
JS_ToInt32(ctx, &_int_b, argv[2]);
unsigned char b = (unsigned char)_int_b;
int _int_a;
JS_ToInt32(ctx, &_int_a, argv[3]);
unsigned char a = (unsigned char)_int_a;
Color _struct = { r, g, b, a };
Color* ptr = (Color*)js_malloc(ctx, sizeof(Color));
*ptr = _struct;
JSValue _return = JS_NewObjectClass(ctx, js_Color_class_id);
JS_SetOpaque(_return, ptr);
return _return;
}
static JSValue js_setWindowTitle(JSContext * ctx, JSValueConst this_val, int argc, JSValueConst * argv) {
const char * title = JS_ToCString(ctx, argv[0]);
if(title == NULL) return JS_EXCEPTION;
@ -165,6 +186,8 @@ static const JSCFunctionListEntry js_raylib_core_funcs[] = {
static int js_raylib_core_init(JSContext * ctx, JSModuleDef * m) {
JS_SetModuleExportList(ctx, m,js_raylib_core_funcs,countof(js_raylib_core_funcs));
js_declare_Color(ctx, m);
JSValue Color_constr = JS_NewCFunction2(ctx, js_Color_constructor,"Color)", 4, JS_CFUNC_constructor_or_func, 0);
JS_SetModuleExport(ctx, m, "Color", Color_constr);
return 0;
}
@ -173,6 +196,7 @@ JSModuleDef * js_init_module_raylib_core(JSContext * ctx, const char * module_na
m = JS_NewCModule(ctx, module_name, js_raylib_core_init);
if(!m) return NULL;
JS_AddModuleExportList(ctx, m, js_raylib_core_funcs, countof(js_raylib_core_funcs));
JS_AddModuleExport(ctx, m, "Color");
return m;
}

2
thirdparty/raylib vendored

@ -1 +1 @@
Subproject commit 5573f0f1c7b29bfe46d0b70487e4adb4d01cba62
Subproject commit a48bb6e1ed7b33190e486ba65b7875f0dff73701