From 83f2c4d786b360fa2b9b57b7d942e015c0ad198f Mon Sep 17 00:00:00 2001 From: tritao Date: Thu, 17 Apr 2025 03:07:40 +0100 Subject: [PATCH] Implement support for properties in Emscripten generator. --- .github/workflows/main.yml | 2 +- src/Generator/Driver.cs | 14 +++++++-- .../Emscripten/EmscriptenSources.cs | 31 +++++++++++++++---- tests/Classes.h | 22 ++++++++++--- tests/emscripten/test.mjs | 9 +++++- tests/emscripten/test.sh | 4 +-- 6 files changed, 66 insertions(+), 16 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c98fea6f..1dcd1211 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -37,7 +37,7 @@ jobs: - uses: actions/checkout@v4 - name: Setup emsdk - uses: mymindstorm/setup-emsdk@v11 + uses: mymindstorm/setup-emsdk@v14 with: version: ${{ env.EMSCRIPTEN_VERSION }} actions-cache-folder: emsdk-cache-${{ runner.os }} diff --git a/src/Generator/Driver.cs b/src/Generator/Driver.cs index f9be9845..cf20a268 100644 --- a/src/Generator/Driver.cs +++ b/src/Generator/Driver.cs @@ -252,7 +252,12 @@ namespace CppSharp passes.AddPass(new CleanInvalidDeclNamesPass()); passes.AddPass(new FastDelegateToDelegatesPass()); - passes.AddPass(new FieldToPropertyPass()); + + if (Options.GeneratorKind != GeneratorKind.Emscripten) + { + passes.AddPass(new FieldToPropertyPass()); + } + passes.AddPass(new CheckIgnoredDeclsPass()); passes.AddPass(new CheckEnumsPass()); passes.AddPass(new MakeProtectedNestedTypesPublicPass()); @@ -283,9 +288,14 @@ namespace CppSharp passes.AddPass(new CheckDuplicatedNamesPass()); - if (Options.IsCLIGenerator || Options.IsCSharpGenerator) + if (Options.IsCLIGenerator || Options.IsCSharpGenerator + || Options.GeneratorKind.ID is GeneratorKind.Emscripten_ID) { passes.RenameDeclsUpperCase(RenameTargets.Any & ~RenameTargets.Parameter); + } + + if (Options.IsCLIGenerator || Options.IsCSharpGenerator) + { passes.AddPass(new CheckKeywordNamesPass()); } diff --git a/src/Generator/Generators/Emscripten/EmscriptenSources.cs b/src/Generator/Generators/Emscripten/EmscriptenSources.cs index 3918ef2a..c1c99a1d 100644 --- a/src/Generator/Generators/Emscripten/EmscriptenSources.cs +++ b/src/Generator/Generators/Emscripten/EmscriptenSources.cs @@ -117,11 +117,6 @@ namespace CppSharp.Generators.Emscripten } } - public override bool VisitProperty(Property property) - { - return true; - } - public override bool VisitMethodDecl(Method method) { Indent(); @@ -130,9 +125,33 @@ namespace CppSharp.Generators.Emscripten return ret; } + public override bool VisitProperty(Property property) + { + if (property.Field != null) + return property.Field.Visit(this); + + if (!property.GetMethod.IsConst) + { + Console.WriteLine($"Cannot bind non-const property getter method: {property.GetMethod.QualifiedOriginalName}"); + return false; + } + + var @class = property.Namespace as Class; + Indent(); + Write($".property(\"{property.Name}\", &{@class.QualifiedOriginalName}::{property.GetMethod.OriginalName}"); + + if (property.HasSetter) + Write($", &{@class.QualifiedOriginalName}::{property.SetMethod.OriginalName}"); + + WriteLine(")"); + Unindent(); + + return true; + } + public override bool VisitFieldDecl(Field field) { - WriteLineIndent($".field(\"{field.Name}\", &{field.Class.QualifiedOriginalName}::{field.OriginalName})"); + WriteLineIndent($".property(\"{field.Name}\", &{field.Class.QualifiedOriginalName}::{field.OriginalName})"); return true; } diff --git a/tests/Classes.h b/tests/Classes.h index 7a43d8a1..718e12ce 100644 --- a/tests/Classes.h +++ b/tests/Classes.h @@ -6,8 +6,8 @@ class Class { public: void ReturnsVoid() {} - int ReturnsInt() { return 0; } - // Class* PassAndReturnsClassPtr(Class* obj) { return obj; } + int ReturnsInt() const { return 0; } + Class* PassAndReturnsClassPtr(Class* obj) { return obj; } }; class ClassWithField @@ -18,7 +18,21 @@ public: { } int Field; - int ReturnsField() { return Field; } + int ReturnsField() const { return Field; } +}; + +class ClassWithProperty +{ +public: + ClassWithProperty() + : Field(10) + { + } + int GetField() const { return Field; } + void SetField(int value) { Field = value; } + +private: + int Field; }; class ClassWithOverloads @@ -41,4 +55,4 @@ class ClassWithExternalInheritance : public ClassFromAnotherUnit }; // void FunctionPassClassByRef(Class* klass) { } -// Class* FunctionReturnsClassByRef() { return new Class(); } \ No newline at end of file +// Class* FunctionReturnsClassByRef() { return new Class(); } diff --git a/tests/emscripten/test.mjs b/tests/emscripten/test.mjs index fc65f55a..f6098892 100644 --- a/tests/emscripten/test.mjs +++ b/tests/emscripten/test.mjs @@ -111,7 +111,14 @@ function classes() { var classWithField = new test.ClassWithField(); eq(classWithField.ReturnsField(), 10); - //eq(classWithField.Field, 10); + eq(classWithField.Field, 10); + classWithField.Field = 20; + eq(classWithField.ReturnsField(), 20); + + var classWithProperty = new test.ClassWithProperty(); + eq(classWithProperty.Field, 10); + classWithProperty.Field = 20; + eq(classWithProperty.Field, 20); } builtins(); diff --git a/tests/emscripten/test.sh b/tests/emscripten/test.sh index d57a13df..2475b43c 100755 --- a/tests/emscripten/test.sh +++ b/tests/emscripten/test.sh @@ -38,8 +38,8 @@ generate=true if [ $generate = true ]; then echo "${green}Generating bindings${reset}" - dotnet $rootdir/bin/${dotnet_configuration}/CppSharp.CLI.dll \ - --gen=emscripten --platform=emscripten --arch=wasm32 \ + dotnet $rootdir/bin/${dotnet_configuration}_${platform}/CppSharp.CLI.dll \ + --gen=emscripten --platform=emscripten --arch=wasm32 --property=keywords \ -I$dir/.. -I$rootdir/include -o $dir/gen -m tests $dir/../*.h fi