mirror of https://github.com/mode777/rayjs.git
WIP binding generator
This commit is contained in:
parent
8b08b72807
commit
70e23cb149
|
@ -1,8 +1,9 @@
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"header": "raylib_core",
|
"name": "raylib_core",
|
||||||
"functions": [
|
"functions": [
|
||||||
{ "name": "SetWindowTitle", "jsName": "setWindowTitle" }
|
{ "name": "SetWindowTitle", "jsName": "setWindowTitle" },
|
||||||
|
{ "name": "SetWindowPosition", "jsName": "setWindowPosition" }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
|
@ -1,16 +1,17 @@
|
||||||
// Run with Node.js
|
// Run with Node.js
|
||||||
|
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
let api, bindings
|
const { connect } = require('http2');
|
||||||
|
let api, modules
|
||||||
|
|
||||||
async function main(){
|
async function main(){
|
||||||
api = await readJson('thirdparty/raylib/parser/output/raylib_api.json')
|
api = await readJson('thirdparty/raylib/parser/output/raylib_api.json')
|
||||||
bindings = await readJson('bindings.json')
|
modules = await readJson('bindings.json')
|
||||||
|
|
||||||
const headers = bindings.map(generateModule)
|
const headers = modules.map(generateModule)
|
||||||
|
|
||||||
bindings.forEach(async (header,i) => {
|
modules.forEach(async (header,i) => {
|
||||||
await writeFile(`js_${header.header}.h`, headers[i])
|
await writeFile(`src/bindings/js_${header.name}.h`, headers[i])
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,20 +19,61 @@ class FunctionList {
|
||||||
definitions = []
|
definitions = []
|
||||||
|
|
||||||
addFunctionDef(name, args, cname){
|
addFunctionDef(name, args, cname){
|
||||||
this.definitions.push(`JS_FUNC_DEF("${name}", ${args}, ${cname})`)
|
this.definitions.push(`JS_CFUNC_DEF("${name}", ${args}, ${cname})`)
|
||||||
}
|
}
|
||||||
|
|
||||||
addIntConst(name, val){
|
addIntConst(name, val){
|
||||||
this.definitions.push(`JS_PROP_INT32_DEF("${name}", ${val})`)
|
this.definitions.push(`JS_PROP_INT32_DEF("${name}", ${val})`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
generate(name){
|
||||||
|
return `static const JSCFunctionListEntry js_${name}_funcs[] = {
|
||||||
|
${this.definitions.map(x => " "+x).join(",\n")}
|
||||||
|
};`
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const generateModule = (mod) => {
|
const generateModule = (mod) => {
|
||||||
|
const fl = new FunctionList()
|
||||||
|
let content = mod.functions.map(generateFunction(fl)).join("\n\n")
|
||||||
|
content += "\n\n" + fl.generate(mod.name)
|
||||||
|
return generateHeader(mod.name, content)
|
||||||
}
|
}
|
||||||
|
|
||||||
const generateFunction = (func) => {
|
const generateFunction = (functionList) => (func) => {
|
||||||
const api = findFunction(func.name)
|
const api = findFunction(func.name)
|
||||||
|
const cfunc = new CFunction(func, api, functionList)
|
||||||
|
return cfunc.generate()
|
||||||
|
}
|
||||||
|
|
||||||
|
const generateParameter = (param,i) => {
|
||||||
|
switch(param.type){
|
||||||
|
case "const char *":
|
||||||
|
return `${param.type} ${param.name} = JS_ToCString(ctx, argv[${i}]);`
|
||||||
|
case "int":
|
||||||
|
return `${param.type} ${param.name};\n JS_ToInt32(ctx, &${param.name}, argv[${i}]);`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CFunction {
|
||||||
|
constructor(func, api, functionList){
|
||||||
|
this.func = func
|
||||||
|
this.api = api
|
||||||
|
this.functionList = functionList
|
||||||
|
this.functionName = `js_${func.jsName}`
|
||||||
|
}
|
||||||
|
|
||||||
|
generateParameters(){
|
||||||
|
return this.api.params.map(generateParameter)
|
||||||
|
}
|
||||||
|
|
||||||
|
generate(){
|
||||||
|
this.functionList.addFunctionDef(this.func.jsName, this.api.params.length, this.functionName)
|
||||||
|
return `static JSValue ${this.functionName}(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv){
|
||||||
|
${this.generateParameters().map(x => " "+x).join("\n")}
|
||||||
|
return JS_UNDEFINED;
|
||||||
|
}`
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const findFunction = (name) => findIn(api.functions,name)
|
const findFunction = (name) => findIn(api.functions,name)
|
||||||
|
@ -63,8 +105,8 @@ function writeFile(path, data){
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function templateHeader(name, content){
|
function generateHeader(name, content){
|
||||||
const res = `
|
return `
|
||||||
#ifndef JS_${name}
|
#ifndef JS_${name}
|
||||||
#define JS_${name}
|
#define JS_${name}
|
||||||
|
|
||||||
|
@ -74,6 +116,10 @@ function templateHeader(name, content){
|
||||||
|
|
||||||
#include <quickjs.h>
|
#include <quickjs.h>
|
||||||
|
|
||||||
|
#ifndef countof
|
||||||
|
#define countof(x) (sizeof(x) / sizeof((x)[0]))
|
||||||
|
#endif
|
||||||
|
|
||||||
${content}
|
${content}
|
||||||
|
|
||||||
static int js_${name}_init(JSContext *ctx, JSModuleDef *m){
|
static int js_${name}_init(JSContext *ctx, JSModuleDef *m){
|
||||||
|
@ -88,6 +134,9 @@ JSModuleDef *js_init_module_${name}(JSContext *ctx, const char *module_name)
|
||||||
if (!m)
|
if (!m)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
JS_AddModuleExportList(ctx, m, js_${name}_funcs,
|
||||||
|
countof(js_${name}_funcs));
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
8
main.js
8
main.js
|
@ -1,9 +1,5 @@
|
||||||
import { test } from "./my-module.js";
|
import { setWindowTitle } from "raylib.core"
|
||||||
|
|
||||||
console.log(test())
|
console.log(setWindowTitle("Test"))
|
||||||
|
|
||||||
async function main(){
|
|
||||||
await Promise.resolve()
|
|
||||||
console.log("Test")
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
|
||||||
|
#ifndef JS_raylib_core
|
||||||
|
#define JS_raylib_core
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <quickjs.h>
|
||||||
|
|
||||||
|
#ifndef countof
|
||||||
|
#define countof(x) (sizeof(x) / sizeof((x)[0]))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static JSValue js_setWindowTitle(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv){
|
||||||
|
const char * title = JS_ToCString(ctx, argv[0]);
|
||||||
|
return JS_UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValue js_setWindowPosition(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv){
|
||||||
|
int x;
|
||||||
|
JS_ToInt32(ctx, &x, argv[0]);
|
||||||
|
int y;
|
||||||
|
JS_ToInt32(ctx, &y, argv[1]);
|
||||||
|
return JS_UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const JSCFunctionListEntry js_raylib_core_funcs[] = {
|
||||||
|
JS_CFUNC_DEF("setWindowTitle", 1, js_setWindowTitle),
|
||||||
|
JS_CFUNC_DEF("setWindowPosition", 2, js_setWindowPosition)
|
||||||
|
};
|
||||||
|
|
||||||
|
static int js_raylib_core_init(JSContext *ctx, JSModuleDef *m){
|
||||||
|
JS_SetModuleExportList(ctx, m, js_raylib_core_funcs,
|
||||||
|
countof(js_raylib_core_funcs));
|
||||||
|
}
|
||||||
|
|
||||||
|
JSModuleDef *js_init_module_raylib_core(JSContext *ctx, const char *module_name)
|
||||||
|
{
|
||||||
|
JSModuleDef *m;
|
||||||
|
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));
|
||||||
|
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <raylib.h>
|
#include <raylib.h>
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "bindings/js_raylib_core.h"
|
||||||
|
|
||||||
static JSContext *JS_NewCustomContext(JSRuntime *rt);
|
static JSContext *JS_NewCustomContext(JSRuntime *rt);
|
||||||
static int eval_buf(JSContext *ctx, const void *buf, int buf_len,
|
static int eval_buf(JSContext *ctx, const void *buf, int buf_len,
|
||||||
|
@ -85,74 +86,12 @@ static JSContext *JS_NewCustomContext(JSRuntime *rt)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* system modules */
|
/* system modules */
|
||||||
js_init_module_std(ctx, "std");
|
//js_init_module_std(ctx, "std");
|
||||||
js_init_module_os(ctx, "os");
|
//js_init_module_os(ctx, "os");
|
||||||
js_init_module_raylib_core(ctx, "raylib.core");
|
js_init_module_raylib_core(ctx, "raylib.core");
|
||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const JSCFunctionListEntry js_raylib_core_funcs[] = {
|
|
||||||
JS_FUNC_DEF("beginDrawing", 0, js_raylib_core_beginDrawing);
|
|
||||||
// JS_CFUNC_DEF("exit", 1, js_std_exit ),
|
|
||||||
// JS_CFUNC_DEF("gc", 0, js_std_gc ),
|
|
||||||
// JS_CFUNC_DEF("evalScript", 1, js_evalScript ),
|
|
||||||
// JS_CFUNC_DEF("loadScript", 1, js_loadScript ),
|
|
||||||
// JS_CFUNC_DEF("getenv", 1, js_std_getenv ),
|
|
||||||
// JS_CFUNC_DEF("setenv", 1, js_std_setenv ),
|
|
||||||
// JS_CFUNC_DEF("unsetenv", 1, js_std_unsetenv ),
|
|
||||||
// JS_CFUNC_DEF("getenviron", 1, js_std_getenviron ),
|
|
||||||
// JS_CFUNC_DEF("urlGet", 1, js_std_urlGet ),
|
|
||||||
// JS_CFUNC_DEF("loadFile", 1, js_std_loadFile ),
|
|
||||||
// JS_CFUNC_DEF("strerror", 1, js_std_strerror ),
|
|
||||||
// JS_CFUNC_DEF("parseExtJSON", 1, js_std_parseExtJSON ),
|
|
||||||
|
|
||||||
// /* FILE I/O */
|
|
||||||
// JS_CFUNC_DEF("open", 2, js_std_open ),
|
|
||||||
// JS_CFUNC_DEF("popen", 2, js_std_popen ),
|
|
||||||
// JS_CFUNC_DEF("fdopen", 2, js_std_fdopen ),
|
|
||||||
// JS_CFUNC_DEF("tmpfile", 0, js_std_tmpfile ),
|
|
||||||
// JS_CFUNC_MAGIC_DEF("puts", 1, js_std_file_puts, 0 ),
|
|
||||||
// JS_CFUNC_DEF("printf", 1, js_std_printf ),
|
|
||||||
// JS_CFUNC_DEF("sprintf", 1, js_std_sprintf ),
|
|
||||||
// JS_PROP_INT32_DEF("SEEK_SET", SEEK_SET, JS_PROP_CONFIGURABLE ),
|
|
||||||
// JS_PROP_INT32_DEF("SEEK_CUR", SEEK_CUR, JS_PROP_CONFIGURABLE ),
|
|
||||||
// JS_PROP_INT32_DEF("SEEK_END", SEEK_END, JS_PROP_CONFIGURABLE ),
|
|
||||||
// JS_OBJECT_DEF("Error", js_std_error_props, countof(js_std_error_props), JS_PROP_CONFIGURABLE),
|
|
||||||
};
|
|
||||||
|
|
||||||
static int js_raylib_core_init(JSContext *ctx, JSModuleDef *m)
|
|
||||||
{
|
|
||||||
JSValue proto;
|
|
||||||
|
|
||||||
// /* FILE class */
|
|
||||||
// /* the class ID is created once */
|
|
||||||
// JS_NewClassID(&js_std_file_class_id);
|
|
||||||
// /* the class is created once per runtime */
|
|
||||||
// JS_NewClass(JS_GetRuntime(ctx), js_std_file_class_id, &js_std_file_class);
|
|
||||||
// proto = JS_NewObject(ctx);
|
|
||||||
// JS_SetPropertyFunctionList(ctx, proto, js_std_file_proto_funcs,
|
|
||||||
// countof(js_std_file_proto_funcs));
|
|
||||||
// JS_SetClassProto(ctx, js_std_file_class_id, proto);
|
|
||||||
|
|
||||||
JS_SetModuleExportList(ctx, m, js_raylib_core_funcs,
|
|
||||||
countof(js_raylib_core_funcs));
|
|
||||||
|
|
||||||
// JS_SetModuleExport(ctx, m, "in", js_new_std_file(ctx, stdin, FALSE, FALSE));
|
|
||||||
// JS_SetModuleExport(ctx, m, "out", js_new_std_file(ctx, stdout, FALSE, FALSE));
|
|
||||||
// JS_SetModuleExport(ctx, m, "err", js_new_std_file(ctx, stderr, FALSE, FALSE));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
JSModuleDef *js_init_module_raylib_core(JSContext *ctx, const char *module_name)
|
|
||||||
{
|
|
||||||
JSModuleDef *m;
|
|
||||||
m = JS_NewCModule(ctx, module_name, js_raylib_core_init);
|
|
||||||
if (!m)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int eval_buf(JSContext *ctx, const void *buf, int buf_len,
|
static int eval_buf(JSContext *ctx, const void *buf, int buf_len,
|
||||||
const char *filename, int eval_flags)
|
const char *filename, int eval_flags)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue