diff --git a/src/Generator/Generators/C/QuickJS/QuickJSModule.cs b/src/Generator/Generators/C/QuickJS/QuickJSModule.cs index 025f1793..18e80901 100644 --- a/src/Generator/Generators/C/QuickJS/QuickJSModule.cs +++ b/src/Generator/Generators/C/QuickJS/QuickJSModule.cs @@ -25,24 +25,39 @@ namespace CppSharp.Generators.Cpp GenerateFilePreamble(CommentKind.BCPL); PushBlock(BlockKind.Includes); - - WriteInclude(new CInclude() - { - File = "quickjs.h", - Kind = CInclude.IncludeKind.Angled - }); - - foreach (var unit in TranslationUnits) { WriteInclude(new CInclude() { - File = GetIncludeFileName(Context, unit), - Kind = CInclude.IncludeKind.Quoted + File = "quickjs.h", + Kind = CInclude.IncludeKind.Angled }); + + foreach (var unit in TranslationUnits) + { + WriteInclude(new CInclude() + { + File = GetIncludeFileName(Context, unit), + Kind = CInclude.IncludeKind.Quoted + }); + } + + NewLine(); } + PopBlock(); + WriteLine("extern \"C\" {"); + NewLine(); + + PushBlock(); + { + foreach (var unit in TranslationUnits) + { + var name = NAPISources.GetTranslationUnitName(unit); + WriteLine($"extern void register_{name}(JSContext *ctx, JSModuleDef *m, bool set);"); + } + } + PopBlock(NewLineKind.BeforeNextBlock); NewLine(); - PopBlock(); WriteLine("#define countof(x) (sizeof(x) / sizeof((x)[0]))"); NewLine(); @@ -70,9 +85,19 @@ namespace CppSharp.Generators.Cpp // Generate init function. WriteLine($"static int js_{moduleName}_init(JSContext* ctx, JSModuleDef* m)"); WriteOpenBraceAndIndent(); - +/* WriteLine($"return JS_SetModuleExportList(ctx, m, js_{moduleName}_funcs," + $" countof(js_{moduleName}_funcs));"); +*/ + + foreach (var unit in TranslationUnits) + { + var name = NAPISources.GetTranslationUnitName(unit); + WriteLine($"register_{name}(ctx, m, /*set=*/true);"); + } + NewLine(); + + WriteLine("return 0;"); UnindentAndWriteCloseBrace(); NewLine(); @@ -94,11 +119,23 @@ namespace CppSharp.Generators.Cpp WriteLineIndent("return nullptr;"); NewLine(); + foreach (var unit in TranslationUnits) + { + var name = NAPISources.GetTranslationUnitName(unit); + WriteLine($"register_{name}(ctx, m, /*set=*/false);"); + } + NewLine(); +/* WriteLine($"JS_AddModuleExportList(ctx, m, js_{moduleName}_funcs," + $" countof(js_{moduleName}_funcs));"); +*/ + WriteLine("return m;"); UnindentAndWriteCloseBrace(); + + NewLine(); + WriteLine("}"); } public static string GetIncludeFileName(BindingContext context, @@ -135,8 +172,10 @@ namespace CppSharp.Generators.Cpp if (!function.IsGenerated) return true; +/* WriteLine($"JS_CFUNC_DEF(\"{function.Name}\"," + $" {function.Parameters.Count}, js_{function.Name}),"); +*/ return true; } diff --git a/src/Generator/Generators/C/QuickJS/QuickJSSources.cs b/src/Generator/Generators/C/QuickJS/QuickJSSources.cs index aca5d745..2c865930 100644 --- a/src/Generator/Generators/C/QuickJS/QuickJSSources.cs +++ b/src/Generator/Generators/C/QuickJS/QuickJSSources.cs @@ -5,6 +5,7 @@ using System.Linq; using CppSharp.AST; using CppSharp.AST.Extensions; using CppSharp.Generators.C; +using static CppSharp.Generators.Cpp.NAPISources; namespace CppSharp.Generators.Cpp { @@ -12,7 +13,7 @@ namespace CppSharp.Generators.Cpp /// Generates QuickJS C/C++ source files. /// QuickJS documentation: https://bellard.org/quickjs/ /// - public class QuickJSSources : NAPICallbacks + public class QuickJSSources : NAPISources { public QuickJSSources(BindingContext context, IEnumerable units) : base(context, units) @@ -24,32 +25,193 @@ namespace CppSharp.Generators.Cpp GenerateFilePreamble(CommentKind.BCPL); PushBlock(BlockKind.Includes); - - WriteInclude(new CInclude() { - File = "quickjs.h", - Kind = CInclude.IncludeKind.Angled - }); + WriteInclude("quickjs.h", CInclude.IncludeKind.Angled); + WriteInclude("assert.h", CInclude.IncludeKind.Angled); - foreach (var unit in TranslationUnits) - { - WriteInclude(new CInclude() + foreach (var unit in TranslationUnits) { - File = unit.IncludePath, - Kind = CInclude.IncludeKind.Angled - }); + WriteInclude(unit.IncludePath, CInclude.IncludeKind.Angled); + } + + NewLine(); } + PopBlock(); + WriteLine("extern \"C\" {"); NewLine(); - PopBlock(); - VisitNamespace(TranslationUnit); + var registerGen = new QuickJSRegister(Context, TranslationUnits); + registerGen.Process(); + WriteLine(registerGen.Generate()); + + PushBlock(); + { + var name = GetTranslationUnitName(TranslationUnit); + WriteLine($"void register_{name}(JSContext *ctx, JSModuleDef *m, bool set)"); + WriteOpenBraceAndIndent(); + + TranslationUnit.Visit(this); + + UnindentAndWriteCloseBrace(); + } + PopBlock(NewLineKind.BeforeNextBlock); + + WriteLine("}"); } - public override NAPICallbacks.ParamMarshal GenerateFunctionParamMarshal(Parameter param, int paramIndex, + public override bool VisitClassDecl(Class @class) + { + if (@class.IsIncomplete) + return true; + + PushBlock(); + WriteLine($"register_class_{GetCIdentifier(Context, @class)}(ctx, m, set);"); + PopBlock(NewLineKind.BeforeNextBlock); + return true; + } + + public override bool VisitFunctionDecl(Function function) + { + if (function.IsOperator) + return true; + + PushBlock(); + WriteLine($"register_function_{GetCIdentifier(Context, function)}(ctx, m, set);"); + PopBlock(NewLineKind.BeforeNextBlock); + return true; + } + + public override bool VisitEnumDecl(Enumeration @enum) + { + if (@enum.IsIncomplete) + return false; + + PushBlock(); + WriteLine($"register_enum_{GetCIdentifier(Context, @enum)}(ctx, m, set);"); + PopBlock(NewLineKind.BeforeNextBlock); + return true; + } + } + + public class QuickJSRegister : NAPIRegister + { + public QuickJSRegister(BindingContext context, IEnumerable units) + : base(context, units) + { + } + + public override bool VisitClassDecl(Class @class) + { + if (@class.IsIncomplete) + return true; + +/* + PushBlock(BlockKind.InternalsClass, @class); + { + var callbacks = new QuickJSInvokes(Context); + @class.Visit(callbacks); + Write(callbacks.Generate()); + } + PopBlock(NewLineKind.BeforeNextBlock); +*/ + + PushBlock(BlockKind.Class, @class); + { + Write($"static void register_class_{GetCIdentifier(Context, @class)}"); + WriteLine("(JSContext *ctx, JSModuleDef *m, bool set)"); + WriteOpenBraceAndIndent(); + +/* + var sources = new NAPIRegisterImpl(Context); + sources.Indent(CurrentIndentation); + @class.Visit(sources); + Write(sources.Generate()); +*/ + + UnindentAndWriteCloseBrace(); + } + PopBlock(NewLineKind.BeforeNextBlock); + + return false; + } + + public override void GenerateFunctionGroup(List group) + { + var function = group.First(); + if (function.IsOperator) + return; + + PushBlock(BlockKind.Function); + { + var callbacks = new QuickJSInvokes(Context); + callbacks.GenerateFunctionGroup(group); + Write(callbacks.Generate()); + } + PopBlock(NewLineKind.BeforeNextBlock); + + PushBlock(BlockKind.Function); + { + Write($"static void register_function_{GetCIdentifier(Context, function)}"); + WriteLine("(JSContext *ctx, JSModuleDef *m, bool set)"); + WriteOpenBraceAndIndent(); + + WriteLine("if (!set)"); + WriteOpenBraceAndIndent(); + WriteLine($"int status = JS_AddModuleExport(ctx, m, \"{function.Name}\");"); + WriteLine("assert(status != -1);"); + WriteLine("return;"); + UnindentAndWriteCloseBrace(); + NewLine(); + + var callbackId = $"callback_function_{GetCIdentifier(Context, function)}"; + var maxParams = @group.Max(f => f.Parameters.Count); + + WriteLine($"JSValue val = JS_NewCFunction(ctx, {callbackId}, \"{function.Name}\"," + + $" {maxParams});"); + WriteLine($"int status = JS_SetModuleExport(ctx, m, \"{function.Name}\", val);"); + WriteLine("assert(status != -1);"); + + UnindentAndWriteCloseBrace(); + } + PopBlock(NewLineKind.BeforeNextBlock); + } + + public override bool VisitEnumDecl(Enumeration @enum) + { + if (@enum.IsIncomplete) + return false; + + PushBlock(BlockKind.Enum); + { + Write($"static void register_enum_{GetCIdentifier(Context, @enum)}"); + WriteLine("(JSContext *ctx, JSModuleDef *m)"); + WriteOpenBraceAndIndent(); + + UnindentAndWriteCloseBrace(); + } + PopBlock(NewLineKind.BeforeNextBlock); + + return true; + } + } + + public class QuickJSInvokes : NAPIInvokes + { + public QuickJSInvokes(BindingContext context) + : base(context, null) + { + } + + public QuickJSInvokes(BindingContext context, IEnumerable units) + : base(context, units) + { + } + + public override ParamMarshal GenerateFunctionParamMarshal(Parameter param, int paramIndex, Function function = null) { - var paramMarshal = new NAPICallbacks.ParamMarshal { Name = param.Name, Param = param }; + var paramMarshal = new ParamMarshal { Name = param.Name, Param = param }; var argName = Generator.GeneratedIdentifier(param.Name); @@ -112,9 +274,12 @@ namespace CppSharp.Generators.Cpp { var function = @group.First(); + var type = function is Method ? "method" : "function"; + var callbackId = $"callback_{type}_{GetCIdentifier(Context, function)}"; + PushBlock(); Write("extern \"C\" "); - WriteLine($"JSValue js_{function.Name}(JSContext* ctx, JSValueConst this_val,"); + WriteLine($"JSValue {callbackId}(JSContext* ctx, JSValueConst this_val,"); WriteLineIndent("int argc, JSValueConst* argv)"); WriteOpenBraceAndIndent();