Browse Source

Merge branch 'mono:main' into main

pull/1862/head
Redux 8 months ago committed by GitHub
parent
commit
7f02b65b81
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 31
      .github/workflows/main.yml
  2. 2
      Directory.Build.props
  3. 1
      Directory.Packages.props
  4. 2
      README.md
  5. 2
      build/Helpers.lua
  6. 14
      build/build.sh
  7. 1
      build/premake5.lua
  8. 19
      build/scripts/ClangToolset.cmake
  9. 117
      build/scripts/Provision.lua
  10. 44
      build/scripts/Vagrantfile
  11. 10
      docs/logo.svg
  12. 52
      src/CLI/CLI.cs
  13. 1
      src/CLI/CppSharp.CLI.csproj
  14. 30
      src/CLI/Generator.cs
  15. 85
      src/CLI/LuaContext.cs
  16. 7
      src/CLI/Options.cs
  17. 7
      src/Generator/Extensions/PrimitiveTypeExtensions.cs
  18. 4
      src/Generator/GeneratorKind.cs
  19. 12
      src/Generator/Generators/Emscripten/EmscriptenGenerator.cs
  20. 5
      src/Generator/Generators/Emscripten/EmscriptenSources.cs
  21. 16
      src/Generator/Generators/QuickJS/QuickJSGenerator.cs
  22. 160
      src/Generator/Generators/QuickJS/QuickJSMarshal.cs
  23. 6
      src/Generator/Generators/QuickJS/QuickJSModule.cs
  24. 58
      src/Generator/Generators/QuickJS/QuickJSSources.cs
  25. 11
      src/Generator/Generators/QuickJS/QuickJSTypeCheckGen.cs
  26. 10
      src/Generator/Generators/QuickJS/Runtime/CppSharp_QuickJS.h
  27. 18
      src/Generator/Generators/QuickJS/Runtime/CppSharp_QuickJS_Signal.cpp
  28. 0
      src/Generator/Generators/QuickJS/Runtime/CppSharp_QuickJS_Signal.h
  29. 3
      src/Generator/Options.cs
  30. 94
      src/Generator/Passes/GetterSetterToPropertyPass.cs
  31. 2
      tests/Builtins.h
  32. 8
      tests/Classes.h
  33. 2
      tests/Classes2.h
  34. 3
      tests/Delegates.h
  35. 2
      tests/Enums.h
  36. 2
      tests/Overloads.h
  37. 1
      tests/emscripten/premake5.lua
  38. 39
      tests/emscripten/test.mjs
  39. 19
      tests/emscripten/test.sh
  40. 8
      tests/napi/test.sh
  41. 3
      tests/quickjs/.gitignore
  42. 22
      tests/quickjs/bindings.lua
  43. 15
      tests/quickjs/bootstrap.sh
  44. 13
      tests/quickjs/premake5.lua
  45. 10
      tests/quickjs/test.js
  46. 20
      tests/quickjs/test.sh
  47. 8
      tests/ts/test.sh

31
.github/workflows/main.yml

@ -10,7 +10,7 @@ jobs: @@ -10,7 +10,7 @@ jobs:
matrix:
config:
- { os: ubuntu-22.04, platform: x64, cxx: g++-11, cc: gcc-11 }
- { os: macos-11, platform: x64, cxx: clang++, cc: clang }
- { os: macos-12, platform: x64, cxx: clang++, cc: clang }
- { os: windows-2022, platform: x64, vs: "Program Files/Microsoft Visual Studio/2022" }
runs-on: ${{ matrix.config.os }}
@ -22,12 +22,24 @@ jobs: @@ -22,12 +22,24 @@ jobs:
PLATFORM: ${{ matrix.config.platform }}
DOTNET_NOLOGO: true
DOTNET_CLI_TELEMETRY_OPTOUT: true
EMSCRIPTEN_VERSION: 3.1.65
steps:
- uses: actions/checkout@v4
with:
fetch-depth: '0'
- name: Setup emsdk
uses: mymindstorm/setup-emsdk@v11
with:
version: ${{ env.EMSCRIPTEN_VERSION }}
actions-cache-folder: emsdk-cache-${{ runner.os }}
- name: Setup cmake
uses: jwlawson/actions-setup-cmake@v2
with:
cmake-version: '3.30.x'
- name: Install nbgv
if: startsWith(matrix.config.os, 'macos')
run: |
@ -55,10 +67,25 @@ jobs: @@ -55,10 +67,25 @@ jobs:
shell: bash
run: build/build.sh -platform $PLATFORM -build_only
- name: Test
- name: Test (.NET)
shell: bash
run: build/test.sh -platform $PLATFORM
- name: Build (QuickJS runtime)
shell: bash
run: tests/quickjs/bootstrap.sh
if: runner.os != 'Windows'
- name: Test (QuickJS)
shell: bash
run: tests/quickjs/test.sh
if: runner.os != 'Windows'
- name: Test (Emscripten)
shell: bash
run: tests/emscripten/test.sh
if: runner.os != 'Windows'
- name: Pack
shell: bash
run: build/build.sh prepack -platform $PLATFORM

2
Directory.Build.props

@ -23,7 +23,7 @@ @@ -23,7 +23,7 @@
<GlobalTargetFramework>$(TargetFramework)</GlobalTargetFramework>
<BaseIntermediateOutputPath>$(ObjDir)$(MSBuildProjectName)\</BaseIntermediateOutputPath>
<BaseOutputPath>$(RootDir)bin\</BaseOutputPath>
<OutputPath>$(BaseOutputPath)$(Configuration)_$(PlatformTarget)\</OutputPath>
<OutputPath>$(BaseOutputPath)$(Configuration)\</OutputPath>
<ActionDir>$(BuildDir)$(PremakeAction)\</ActionDir>
<NativeProjectsDir>$(ActionDir)projects\</NativeProjectsDir>
<PackageDir>$(RootDir)artifacts\package\</PackageDir>

1
Directory.Packages.props

@ -4,5 +4,6 @@ @@ -4,5 +4,6 @@
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
<PackageVersion Include="NUnit" Version="3.13.2" />
<PackageVersion Include="NUnit3TestAdapter" Version="4.0.0" />
<PackageVersion Include="MoonSharp" Version="2.0.0" />
</ItemGroup>
</Project>

2
README.md

@ -1,3 +1,5 @@ @@ -1,3 +1,5 @@
<img src="docs/logo.svg" width="128">
CppSharp is a tool and set of libraries which facilitates the usage of native C/C++ code
with the .NET ecosystem.

2
build/Helpers.lua

@ -59,7 +59,7 @@ bindir = path.join(rootdir, "bin") @@ -59,7 +59,7 @@ bindir = path.join(rootdir, "bin")
objsdir = path.join(builddir, "obj");
gendir = path.join(builddir, "gen");
actionbuilddir = path.join(builddir, _ACTION == "gmake2" and "gmake" or (_ACTION and _ACTION or ""));
bindircfg = path.join(bindir, "%{cfg.buildcfg}_%{cfg.platform}");
bindircfg = path.join(bindir, "%{cfg.buildcfg}");
prjobjdir = path.join(objsdir, "%{prj.name}", "%{cfg.buildcfg}")
msvc_buildflags = { "/MP", "/wd4267" }

14
build/build.sh

@ -54,6 +54,18 @@ generate() @@ -54,6 +54,18 @@ generate()
{
download_llvm
if [ "$target_framework" = "" ]; then
if command -v dotnet &> /dev/null
then
version=$(dotnet --version)
major_minor=$(echo $version | awk -F. '{print $1"."$2}')
target_framework="net$major_minor"
else
echo ".NET is not installed, cannot lookup up target framework version."
fi
fi
if [ "$os" = "linux" ] || [ "$os" = "macosx" ]; then
"$builddir/premake.sh" --file="$builddir/premake5.lua" gmake2 --os=$os --arch=$platform --configuration=$configuration --target-framework=$target_framework "$@"
fi
@ -87,7 +99,7 @@ pack() @@ -87,7 +99,7 @@ pack()
test()
{
dotnet test {"$bindir/${configuration}_$platform","$gendir"/*}/*.Tests*.dll --nologo
dotnet test {"$bindir/${configuration}","$gendir"/*}/*.Tests*.dll --nologo
}
clean()

1
build/premake5.lua

@ -53,7 +53,6 @@ workspace "CppSharp" @@ -53,7 +53,6 @@ workspace "CppSharp"
if EnabledManagedProjects() then
include (srcdir .. "/Core")
include (srcdir .. "/AST")
--include (srcdir .. "/ASTViewer")
include (srcdir .. "/CppParser/Bindings")
include (srcdir .. "/CppParser/Bootstrap")
include (srcdir .. "/CppParser/ParserGen")

19
build/scripts/ClangToolset.cmake

@ -1,19 +0,0 @@ @@ -1,19 +0,0 @@
SET (CMAKE_C_COMPILER "/usr/bin/clang")
SET (CMAKE_C_FLAGS "-Wall -std=c99")
SET (CMAKE_C_FLAGS_DEBUG "-glldb")
SET (CMAKE_C_FLAGS_MINSIZEREL "-Os -DNDEBUG")
SET (CMAKE_C_FLAGS_RELEASE "-O4 -DNDEBUG")
SET (CMAKE_C_FLAGS_RELWITHDEBINFO "-O2 -glldb")
SET (CMAKE_CXX_COMPILER "/usr/bin/clang++")
SET (CMAKE_CXX_FLAGS "-Wall")
SET (CMAKE_CXX_FLAGS_DEBUG "-glldb")
SET (CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG")
SET (CMAKE_CXX_FLAGS_RELEASE "-O4 -DNDEBUG")
SET (CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -glldb")
SET (CMAKE_AR "/usr/bin/llvm-ar")
SET (CMAKE_LINKER "/usr/bin/llvm-ld")
SET (CMAKE_NM "/usr/bin/llvm-nm")
SET (CMAKE_OBJDUMP "/usr/bin/llvm-objdump")
SET (CMAKE_RANLIB "/usr/bin/llvm-ranlib")

117
build/scripts/Provision.lua

@ -1,117 +0,0 @@ @@ -1,117 +0,0 @@
require "Utils"
function download_ninja()
local system = "";
if os.ishost("windows") then
system = "win"
elseif os.ishost("macosx") then
system = "mac"
elseif os.ishost("linux") then
system = "linux"
else
error("Error downloading Ninja for unknown system")
end
local url = "https://github.com/ninja-build/ninja/releases/download/v1.6.0/ninja-" .. system .. ".zip"
local file = "ninja.zip"
if not os.isfile(file) then
download(url, file)
end
if os.isfile(file) then
print("Extracting file " .. file)
zip.extract(file, "ninja")
end
end
function download_cmake()
local system = "";
if os.ishost("windows") then
system = "win32-x86.zip"
elseif os.ishost("macosx") then
system = "Darwin-x86_64.dmg"
elseif os.ishost("linux") then
system = "Linux-x86_64.sh"
else
error("Error downloading CMake for unknown system")
end
local base = "cmake-3.8.2-"
local file = base .. system
local url = "https://cmake.org/files/v3.8/" .. file
if not os.isfile(file) then
download(url, file)
end
return file
end
function download_nuget()
if not os.isfile("nuget.exe") then
download("https://nuget.org/nuget.exe", "nuget.exe")
end
end
function restore_nuget_packages()
local nugetexe = os.ishost("windows") and "NuGet.exe" or "mono ./NuGet.exe"
execute(nugetexe .. " restore packages.config -PackagesDirectory " .. path.join(rootdir, "deps"))
end
local compile_llvm = is_vagrant()
function provision_linux()
-- Add Repos
sudo("apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF")
sudo("echo \"deb http://download.mono-project.com/repo/ubuntu xenial main\" | sudo tee /etc/apt/sources.list.d/mono-xamarin.list")
sudo("apt-get update")
-- Build tools
sudo("apt-get install -y git build-essential clang")
-- Mono
sudo("apt-get install -y mono-devel")
-- LLVM/Clang build tools
if compile_llvm then
sudo("apt-get install -y ninja-build")
local file = download_cmake()
sudo("mkdir -p /opt/cmake")
sudo("bash " .. file .. " --prefix=/opt/cmake --skip-license")
sudo("ln -s /opt/cmake/bin/cmake /usr/local/bin/cmake")
end
end
function brew_install(pkg)
-- check if package is already installed
local res = outputof("brew ls --versions " .. pkg)
if string.is_empty(res) then
execute("brew install " .. pkg)
end
end
function provision_osx()
if compile_llvm then
execute("brew cask install virtualbox vagrant")
end
download_cmake()
end
if _ACTION == "cmake" then
download_cmake()
os.exit()
end
if _ACTION == "provision" then
if os.ishost("linux") then
provision_linux()
elseif os.ishost("macosx") then
provision_osx()
end
os.exit()
end

44
build/scripts/Vagrantfile vendored

@ -1,44 +0,0 @@ @@ -1,44 +0,0 @@
# -*- mode: ruby -*-
# vi: set ft=ruby :
$script = <<SCRIPT
SCRIPT
is_windows = (RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/)
Vagrant.configure(2) do |config|
# For a complete reference, please see the online documentation at
# https://docs.vagrantup.com.
config.vm.box = "geerlingguy/ubuntu1604"
#load external box config
config.vm.provider "virtualbox" do |vb|
vb.memory = 8192
vb.cpus = 4
vb.customize ["setextradata", :id, "VBoxInternal2/SharedFoldersEnableSymlinksCreate//cppsharp","1"]
end
config.vm.network "private_network", type: "dhcp"
config.vm.synced_folder "../..", "/cppsharp", nfs: !is_windows
# this function fixes errors with ubuntu interactive shell
config.vm.provision "fix-no-tty", type: "shell" do |s|
s.privileged = false
s.inline = "sudo sed -i '/tty/!s/mesg n/tty -s \\&\\& mesg n/' /root/.profile"
end
#this section runs as root
config.vm.provision "shell", privileged: true , inline: <<-SHELL
cd /cppsharp/
cd build/scripts && ../premake5-linux-64 --file=Provision.lua provision
SHELL
#this section runs as normal user
config.vm.provision "shell", privileged: false , inline: <<-SHELL
SHELL
end

10
docs/logo.svg

@ -0,0 +1,10 @@ @@ -0,0 +1,10 @@
<svg width="256" height="288" preserveAspectRatio="xMidYMid" xmlns="http://www.w3.org/2000/svg">
<path d="M255.569 84.452c-.002-4.83-1.035-9.098-3.124-12.76-2.052-3.603-5.125-6.622-9.247-9.009-34.025-19.619-68.083-39.178-102.097-58.817-9.17-5.294-18.061-5.1-27.163.27-13.543 7.986-81.348 46.833-101.553 58.536C4.064 67.49.015 74.862.013 84.443 0 123.898.013 163.353 0 202.808c0 4.724.991 8.91 2.988 12.517 2.053 3.711 5.169 6.813 9.386 9.254 20.206 11.703 88.02 50.547 101.56 58.536 9.106 5.373 17.997 5.565 27.17.27 34.015-19.64 68.075-39.199 102.105-58.818 4.217-2.44 7.333-5.544 9.386-9.252 1.994-3.608 2.987-7.793 2.987-12.518 0 0 0-78.889-.013-118.345" fill="#A179DC" />
<path d="M128.182 143.241 2.988 215.325c2.053 3.711 5.169 6.813 9.386 9.254 20.206 11.703 88.02 50.547 101.56 58.536 9.106 5.373 17.997 5.565 27.17.27 34.015-19.64 68.075-39.199 102.105-58.818 4.217-2.44 7.333-5.544 9.386-9.252l-124.413-72.074" fill="#280068" />
<path d="M255.569 84.452c-.002-4.83-1.035-9.098-3.124-12.76l-124.263 71.55 124.413 72.073c1.994-3.608 2.985-7.793 2.987-12.518 0 0 0-78.889-.013-118.345" fill="#390091" />
<path d="M201.892 116.294v13.474h13.474v-13.474h6.737v13.474h13.474v6.737h-13.474v13.473h13.474v6.737h-13.474v13.474h-6.737v-13.474h-13.474v13.474h-6.737v-13.474h-13.473v-6.737h13.473v-13.473h-13.473v-6.737h13.473v-13.474h6.737Zm13.474 20.21h-13.474v13.474h13.474v-13.473Z" fill="#FFF" />
<path d="M128.457 48.626c35.144 0 65.827 19.086 82.262 47.456l-.16-.273-41.35 23.808c-8.146-13.793-23.08-23.102-40.213-23.294l-.54-.003c-26.125 0-47.305 21.18-47.305 47.305a47.08 47.08 0 0 0 6.239 23.47c8.154 14.235 23.483 23.836 41.067 23.836 17.693 0 33.109-9.723 41.221-24.11l-.197.345 41.287 23.918c-16.255 28.13-46.518 47.157-81.253 47.536l-1.058.006c-35.255 0-66.025-19.204-82.419-47.724-8.003-13.923-12.582-30.064-12.582-47.277 0-52.466 42.532-95 95-95Z" fill="#FFF" />
<text xml:space="preserve" style="font-style:normal;font-weight:400;font-size:40px;line-height:1.25;font-family:sans-serif;fill:#fff;fill-opacity:.99012429;stroke:none" x="95.515" y="156.434">
<tspan x="95.515" y="156.434">++</tspan>
</text>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

52
src/CLI/CLI.cs

@ -3,6 +3,7 @@ using System.Collections.Generic; @@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using CppSharp.Generators;
using CppSharp.Passes;
using Mono.Options;
namespace CppSharp
@ -34,6 +35,7 @@ namespace CppSharp @@ -34,6 +35,7 @@ namespace CppSharp
optionSet.Add("p=|platform=", "the {PLATFORM} that the generated code will target: 'win', 'osx' or 'linux' or 'emscripten'", p => { GetDestinationPlatform(p, errorMessages); });
optionSet.Add("a=|arch=", "the {ARCHITECTURE} that the generated code will target: 'x86' or 'x64' or 'wasm32' or 'wasm64'", a => { GetDestinationArchitecture(a, errorMessages); });
optionSet.Add("prefix=", "sets a string prefix to the names of generated files", a => { options.Prefix = a; });
optionSet.Add("property=", "the property detection mode to use: 'all', 'none' or 'keywords' or 'heuristics'", p => { GetPropertyMode(p, errorMessages); });
optionSet.Add("exceptions", "enables support for C++ exceptions in the parser", v => { options.EnableExceptions = true; });
optionSet.Add("rtti", "enables support for C++ RTTI in the parser", v => { options.EnableRTTI = true; });
@ -152,9 +154,16 @@ namespace CppSharp @@ -152,9 +154,16 @@ namespace CppSharp
{
bool searchQuery = args.IndexOf('*') >= 0 || args.IndexOf('?') >= 0;
if (searchQuery || Directory.Exists(args))
{
GetFilesFromPath(args, errorMessages);
}
else if (File.Exists(args))
{
if (Path.GetExtension(args) == ".lua")
options.LuaBindingsFiles.Add(args);
else
options.HeaderFiles.Add(args);
}
else
{
errorMessages.Add($"File '{args}' could not be found.");
@ -175,7 +184,8 @@ namespace CppSharp @@ -175,7 +184,8 @@ namespace CppSharp
if (lastSeparatorPosition >= 0)
{
if (path.IndexOf('*', lastSeparatorPosition) >= lastSeparatorPosition || path.IndexOf('?', lastSeparatorPosition) >= lastSeparatorPosition)
if (path.IndexOf('*', lastSeparatorPosition) >= lastSeparatorPosition ||
path.IndexOf('?', lastSeparatorPosition) >= lastSeparatorPosition)
{
searchPattern = path.Substring(lastSeparatorPosition + 1);
path = path.Substring(0, lastSeparatorPosition);
@ -204,7 +214,7 @@ namespace CppSharp @@ -204,7 +214,7 @@ namespace CppSharp
}
}
static void GetGeneratorKind(string generator, List<string> errorMessages)
public static void GetGeneratorKind(string generator, List<string> errorMessages)
{
foreach (GeneratorKind generatorKind in GeneratorKind.Registered)
{
@ -218,7 +228,7 @@ namespace CppSharp @@ -218,7 +228,7 @@ namespace CppSharp
errorMessages.Add($"Unknown generator kind: {generator}.");
}
static void GetDestinationPlatform(string platform, List<string> errorMessages)
public static void GetDestinationPlatform(string platform, List<string> errorMessages)
{
switch (platform.ToLower())
{
@ -239,7 +249,7 @@ namespace CppSharp @@ -239,7 +249,7 @@ namespace CppSharp
errorMessages.Add($"Unknown target platform: {platform}. Defaulting to {options.Platform}");
}
static void GetDestinationArchitecture(string architecture, List<string> errorMessages)
public static void GetDestinationArchitecture(string architecture, List<string> errorMessages)
{
switch (architecture.ToLower())
{
@ -257,7 +267,29 @@ namespace CppSharp @@ -257,7 +267,29 @@ namespace CppSharp
return;
}
errorMessages.Add($"Unknown target architecture: {architecture}. Defaulting to {options.Architecture}");
errorMessages.Add($@"Unknown target architecture: {architecture}. \
Defaulting to {options.Architecture}");
}
static void GetPropertyMode(string mode, List<string> errorMessages)
{
switch (mode.ToLower())
{
case "all":
options.PropertyMode = PropertyDetectionMode.All;
return;
case "none":
options.PropertyMode = PropertyDetectionMode.None;
return;
case "dictionary":
options.PropertyMode = PropertyDetectionMode.Dictionary;
return;
case "keywords":
options.PropertyMode = PropertyDetectionMode.Keywords;
return;
}
errorMessages.Add($"Unknown property detection mode: {mode}. Defaulting to {options.PropertyMode}");
}
static void PrintErrorMessages(List<string> errorMessages)
@ -275,10 +307,18 @@ namespace CppSharp @@ -275,10 +307,18 @@ namespace CppSharp
{
PrintErrorMessages(errorMessages);
// Don't need to show the help since if ParseCommandLineArgs returns false the help has already been shown
// Don't need to show the help since if ParseCommandLineArgs returns false
// since the help has already been shown
return;
}
var luaContext = new LuaContext(options, errorMessages);
foreach (var luaFile in options.LuaBindingsFiles)
{
Directory.SetCurrentDirectory(Path.GetDirectoryName(luaFile));
luaContext.LoadFile(luaFile);
}
var gen = new Generator(options);
var validOptions = gen.ValidateOptions(errorMessages);

1
src/CLI/CppSharp.CLI.csproj

@ -5,5 +5,6 @@ @@ -5,5 +5,6 @@
<ItemGroup>
<ProjectReference Include="..\Generator\CppSharp.Generator.csproj" />
<PackageReference Include="MoonSharp" />
</ItemGroup>
</Project>

30
src/CLI/Generator.cs

@ -91,6 +91,21 @@ namespace CppSharp @@ -91,6 +91,21 @@ namespace CppSharp
options.OutputDir = Path.Combine(Directory.GetCurrentDirectory(), "gen");
}
if (string.IsNullOrEmpty(options.OutputFileName))
options.OutputFileName = GetModuleNameFromHeaderFiles();
if (string.IsNullOrEmpty(options.OutputNamespace))
options.OutputNamespace = GetModuleNameFromHeaderFiles();
if (options.IncludeDirs.Count == 0)
options.IncludeDirs.Add(Path.GetDirectoryName(options.HeaderFiles.First()));
SetupTargetTriple();
return true;
string GetModuleNameFromHeaderFiles()
{
string moduleName;
if (options.HeaderFiles.Count == 1)
{
@ -102,18 +117,8 @@ namespace CppSharp @@ -102,18 +117,8 @@ namespace CppSharp
moduleName = new DirectoryInfo(dir).Name;
}
if (string.IsNullOrEmpty(options.OutputFileName))
options.OutputFileName = moduleName;
if (string.IsNullOrEmpty(options.OutputNamespace))
options.OutputNamespace = moduleName;
if (options.IncludeDirs.Count == 0)
options.IncludeDirs.Add(Path.GetDirectoryName(options.HeaderFiles.First()));
SetupTargetTriple();
return true;
return moduleName;
}
}
public void Setup(Driver driver)
@ -124,6 +129,7 @@ namespace CppSharp @@ -124,6 +129,7 @@ namespace CppSharp
var driverOptions = driver.Options;
driverOptions.GeneratorKind = options.Kind;
driverOptions.PropertyDetectionMode = options.PropertyMode;
var module = driverOptions.AddModule(options.OutputFileName);
if (!string.IsNullOrEmpty(options.InputLibraryName))

85
src/CLI/LuaContext.cs

@ -0,0 +1,85 @@ @@ -0,0 +1,85 @@
using System;
using System.Collections.Generic;
using System.IO;
using CppSharp;
using MoonSharp.Interpreter;
class LuaContext
{
public Script script;
public Options options;
public List<string> errorMessages;
public string CurrentModule;
public LuaContext(Options options, List<string> errorMessages)
{
this.options = options;
this.errorMessages = errorMessages;
script = new Script(CoreModules.Basic | CoreModules.String |
CoreModules.Table | CoreModules.TableIterators);
script.Globals["generator"] = (string kind) =>
{
CLI.GetGeneratorKind(kind, errorMessages);
};
script.Globals["platform"] = (string platform) =>
{
CLI.GetDestinationPlatform(platform, errorMessages);
};
script.Globals["architecture"] = (string arch) =>
{
CLI.GetDestinationArchitecture(arch, errorMessages);
};
script.Globals["output"] = script.Globals["location"] = (string dir) =>
{
options.OutputDir = dir;
};
script.Globals["includedirs"] = (List<string> dirs) =>
{
foreach (var dir in dirs)
{
options.IncludeDirs.Add(dir);
}
};
script.Globals["module"] = (string name) =>
{
CurrentModule = name;
options.OutputFileName = name;
};
script.Globals["namespace"] = (string name) =>
{
options.OutputNamespace = name;
};
script.Globals["headers"] = (List<string> files) =>
{
foreach (var file in files)
{
options.HeaderFiles.Add(file);
}
};
}
public DynValue LoadFile(string luaFile)
{
var code = script.LoadFile(luaFile);
try
{
return code.Function.Call();
}
catch (Exception ex)
{
Console.Error.WriteLine($"Error running {Path.GetFileName(luaFile)}:\n{ex.Message}");
return null;
}
}
}

7
src/CLI/Options.cs

@ -1,5 +1,6 @@ @@ -1,5 +1,6 @@
using System.Collections.Generic;
using CppSharp.Generators;
using CppSharp.Passes;
namespace CppSharp
{
@ -13,6 +14,8 @@ namespace CppSharp @@ -13,6 +14,8 @@ namespace CppSharp
class Options
{
public List<string> LuaBindingsFiles { get; } = new List<string>();
public List<string> HeaderFiles { get; } = new List<string>();
public List<string> IncludeDirs { get; } = new List<string>();
@ -37,10 +40,12 @@ namespace CppSharp @@ -37,10 +40,12 @@ namespace CppSharp
public TargetPlatform? Platform { get; set; }
public TargetArchitecture Architecture { get; set; } = TargetArchitecture.x86;
public TargetArchitecture Architecture { get; set; } = TargetArchitecture.x64;
public GeneratorKind Kind { get; set; } = GeneratorKind.CSharp;
public PropertyDetectionMode PropertyMode { get; set; } = PropertyDetectionMode.Keywords;
public bool CheckSymbols { get; set; }
public bool UnityBuild { get; set; }

7
src/Generator/Extensions/PrimitiveTypeExtensions.cs

@ -34,6 +34,11 @@ namespace CppSharp.Extensions @@ -34,6 +34,11 @@ namespace CppSharp.Extensions
switch (primitive)
{
case PrimitiveType.Void:
case PrimitiveType.Null:
case PrimitiveType.String:
return (0, 0);
case PrimitiveType.Bool:
return (targetInfo.BoolWidth, targetInfo.BoolAlign);
@ -97,7 +102,7 @@ namespace CppSharp.Extensions @@ -97,7 +102,7 @@ namespace CppSharp.Extensions
return (targetInfo.PointerWidth, targetInfo.PointerAlign);
default:
throw new NotImplementedException();
throw new Exception($"Not implemented for {primitive}");
}
}
}

4
src/Generator/GeneratorKind.cs

@ -59,7 +59,7 @@ namespace CppSharp.Generators @@ -59,7 +59,7 @@ namespace CppSharp.Generators
{
return false;
}
return CLIOptions.Any(cliOption.Contains);
return CLIOptions.Any(option => option == cliOption);
}
public static bool operator ==(GeneratorKind obj1, GeneratorKind obj2)
@ -134,7 +134,7 @@ namespace CppSharp.Generators @@ -134,7 +134,7 @@ namespace CppSharp.Generators
public static readonly GeneratorKind Swift = new(Swift_ID, "Swift", typeof(NotImplementedGenerator), typeof(NotImplementedTypePrinter));
public const string QuickJS_ID = "QuickJS";
public static readonly GeneratorKind QuickJS = new(QuickJS_ID, "QuickJS", typeof(QuickJSGenerator), typeof(QuickJSTypePrinter), new[] { "qjs" });
public static readonly GeneratorKind QuickJS = new(QuickJS_ID, "QuickJS", typeof(QuickJSGenerator), typeof(QuickJSTypePrinter), new[] { "quickjs", "qjs" });
public const string NAPI_ID = "NAPI";
public static readonly GeneratorKind NAPI = new(NAPI_ID, "N-API", typeof(NAPIGenerator), typeof(NAPITypePrinter), new[] { "napi" });

12
src/Generator/Generators/Emscripten/EmscriptenGenerator.cs

@ -13,6 +13,16 @@ namespace CppSharp.Generators.Emscripten @@ -13,6 +13,16 @@ namespace CppSharp.Generators.Emscripten
{
public EmscriptenGenerator(BindingContext context) : base(context)
{
if (context.Options.GenerateName == null)
{
context.Options.GenerateName = (unit) =>
{
if (unit.FileName == "premake5.lua")
return unit.FileNameWithoutExtension;
else
return $"{unit.Module.LibraryName}_embind_{unit.FileNameWithoutExtension}";
};
}
}
public override List<GeneratorOutput> Generate()
@ -59,7 +69,7 @@ namespace CppSharp.Generators.Emscripten @@ -59,7 +69,7 @@ namespace CppSharp.Generators.Emscripten
{
TranslationUnit = new TranslationUnit
{
FilePath = $"{module.LibraryName}_embind_module.cpp",
FilePath = $"_Module.cpp",
Module = module
},
Outputs = new List<CodeGenerator> { moduleGen }

5
src/Generator/Generators/Emscripten/EmscriptenSources.cs

@ -117,6 +117,11 @@ namespace CppSharp.Generators.Emscripten @@ -117,6 +117,11 @@ namespace CppSharp.Generators.Emscripten
}
}
public override bool VisitProperty(Property property)
{
return true;
}
public override bool VisitMethodDecl(Method method)
{
Indent();

16
src/Generator/Generators/QuickJS/QuickJSGenerator.cs

@ -12,6 +12,16 @@ namespace CppSharp.Generators.C @@ -12,6 +12,16 @@ namespace CppSharp.Generators.C
{
public QuickJSGenerator(BindingContext context) : base(context)
{
if (context.Options.GenerateName == null)
{
context.Options.GenerateName = (unit) =>
{
if (unit.FileName == "premake5.lua")
return unit.FileNameWithoutExtension;
else
return $"{unit.Module.LibraryName}_JS_{unit.FileNameWithoutExtension}";
};
}
}
public override List<GeneratorOutput> Generate()
@ -45,8 +55,8 @@ namespace CppSharp.Generators.C @@ -45,8 +55,8 @@ namespace CppSharp.Generators.C
{
var outputs = new List<CodeGenerator>();
var header = new QuickJSHeaders(Context, units);
outputs.Add(header);
// var header = new QuickJSHeaders(Context, units);
// outputs.Add(header);
var source = new QuickJSSources(Context, units);
outputs.Add(source);
@ -65,7 +75,7 @@ namespace CppSharp.Generators.C @@ -65,7 +75,7 @@ namespace CppSharp.Generators.C
{
TranslationUnit = new TranslationUnit
{
FilePath = $"{module.LibraryName}_qjs_module.cpp",
FilePath = $"_Module.cpp",
Module = module
},
Outputs = new List<CodeGenerator> { moduleGen }

160
src/Generator/Generators/QuickJS/QuickJSMarshal.cs

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
using System;
using CppSharp.AST;
using CppSharp.AST.Extensions;
using CppSharp.Extensions;
using CppSharp.Generators.C;
using CppSharp.Generators.CLI;
using CppSharp.Types;
@ -61,34 +62,22 @@ namespace CppSharp.Generators.Cpp @@ -61,34 +62,22 @@ namespace CppSharp.Generators.Cpp
var pointee = pointer.Pointee.Desugar();
PrimitiveType primitive;
var param = Context.Parameter;
if (param != null && (param.IsOut || param.IsInOut) &&
pointee.IsPrimitiveType(out primitive))
pointee.IsPrimitiveType(out _))
{
Context.Return.Write(Context.ReturnVarName);
return true;
}
if (pointee.IsPrimitiveType(out primitive))
if (pointee.IsPrimitiveType(out _))
{
var returnVarName = Context.ReturnVarName;
if (pointer.GetFinalQualifiedPointee().Qualifiers.IsConst !=
Context.ReturnType.Qualifiers.IsConst)
{
var nativeTypePrinter = new CppTypePrinter(Context.Context)
{ PrintTypeQualifiers = false };
var returnType = Context.ReturnType.Type.Desugar();
var constlessPointer = new PointerType()
if (pointer.IsConstCharString())
{
IsDependent = pointer.IsDependent,
Modifier = pointer.Modifier,
QualifiedPointee = new QualifiedType(returnType.GetPointee())
};
var nativeConstlessTypeName = constlessPointer.Visit(nativeTypePrinter, new TypeQualifiers());
returnVarName = string.Format("const_cast<{0}>({1})",
nativeConstlessTypeName, Context.ReturnVarName);
var retName = Generator.GeneratedIdentifier(Context.ReturnVarName);
Context.Before.Write($"JSValue {retName} = JS_NewString(ctx, {Context.ArgName});");
Context.Return.Write(retName);
return true;
}
if (pointer.Pointee is TypedefType)
@ -101,19 +90,17 @@ namespace CppSharp.Generators.Cpp @@ -101,19 +90,17 @@ namespace CppSharp.Generators.Cpp
};
var nativeTypeName = desugaredPointer.Visit(typePrinter, quals);
Context.Return.Write("reinterpret_cast<{0}>({1})", nativeTypeName,
returnVarName);
Context.ReturnVarName);
}
else
Context.Return.Write(returnVarName);
Context.Return.Write(Context.ReturnVarName);
return true;
}
TypeMap typeMap = null;
Context.Context.TypeMaps.FindTypeMap(pointee, out typeMap);
Context.Context.TypeMaps.FindTypeMap(pointee, out var typeMap);
Class @class;
if (pointee.TryGetClass(out @class) && typeMap == null)
if (pointee.TryGetClass(out var @class) && typeMap == null)
{
var instance = (pointer.IsReference) ? "&" + Context.ReturnVarName
: Context.ReturnVarName;
@ -146,10 +133,14 @@ namespace CppSharp.Generators.Cpp @@ -146,10 +133,14 @@ namespace CppSharp.Generators.Cpp
var retName = Generator.GeneratedIdentifier(Context.ReturnVarName);
Context.Before.Write($"JSValue {retName} = ");
(uint width, uint _alignment) =
primitive.GetInfo(Context.Context.TargetInfo, out bool _signed);
switch (primitive)
{
case PrimitiveType.Void:
return true;
Context.Before.WriteLine("JS_UNDEFINED;");
break;
case PrimitiveType.Bool:
Context.Before.WriteLine($"JS_NewBool(ctx, {Context.ArgName});");
@ -163,13 +154,22 @@ namespace CppSharp.Generators.Cpp @@ -163,13 +154,22 @@ namespace CppSharp.Generators.Cpp
case PrimitiveType.UChar:
case PrimitiveType.Short:
case PrimitiveType.UShort:
Context.Before.WriteLine($"JS_NewInt32(ctx, {Context.ArgName});");
break;
case PrimitiveType.Int:
case PrimitiveType.Long:
if (width == 64)
Context.Before.WriteLine($"JS_NewBigInt64(ctx, {Context.ArgName});");
else
Context.Before.WriteLine($"JS_NewInt32(ctx, {Context.ArgName});");
break;
case PrimitiveType.UInt:
case PrimitiveType.ULong:
if (width == 64)
Context.Before.WriteLine($"JS_NewBigUint64(ctx, {Context.ArgName});");
else
Context.Before.WriteLine($"JS_NewUint32(ctx, {Context.ArgName});");
break;
@ -205,8 +205,7 @@ namespace CppSharp.Generators.Cpp @@ -205,8 +205,7 @@ namespace CppSharp.Generators.Cpp
{
var decl = typedef.Declaration;
TypeMap typeMap;
if (Context.Context.TypeMaps.FindTypeMap(decl.Type, out typeMap) &&
if (Context.Context.TypeMaps.FindTypeMap(decl.Type, out var typeMap) &&
typeMap.DoesMarshalling)
{
typeMap.Type = typedef;
@ -214,8 +213,7 @@ namespace CppSharp.Generators.Cpp @@ -214,8 +213,7 @@ namespace CppSharp.Generators.Cpp
return typeMap.IsValueType;
}
FunctionType function;
if (decl.Type.IsPointerTo(out function))
if (decl.Type.IsPointerTo(out FunctionType _))
{
var typeName = typePrinter.VisitDeclaration(decl);
var typeName2 = decl.Type.Visit(typePrinter);
@ -228,8 +226,7 @@ namespace CppSharp.Generators.Cpp @@ -228,8 +226,7 @@ namespace CppSharp.Generators.Cpp
public override bool VisitTemplateSpecializationType(TemplateSpecializationType template,
TypeQualifiers quals)
{
TypeMap typeMap;
if (Context.Context.TypeMaps.FindTypeMap(template, out typeMap) && typeMap.DoesMarshalling)
if (Context.Context.TypeMaps.FindTypeMap(template, out var typeMap) && typeMap.DoesMarshalling)
{
typeMap.Type = template;
typeMap.MarshalToManaged(Context);
@ -382,8 +379,7 @@ namespace CppSharp.Generators.Cpp @@ -382,8 +379,7 @@ namespace CppSharp.Generators.Cpp
public override bool VisitType(Type type, TypeQualifiers quals)
{
TypeMap typeMap;
if (Context.Context.TypeMaps.FindTypeMap(type, out typeMap) && typeMap.DoesMarshalling)
if (Context.Context.TypeMaps.FindTypeMap(type, out var typeMap) && typeMap.DoesMarshalling)
{
typeMap.MarshalToNative(Context);
return false;
@ -443,8 +439,7 @@ namespace CppSharp.Generators.Cpp @@ -443,8 +439,7 @@ namespace CppSharp.Generators.Cpp
return VisitDelegateType(cppTypeName);
}
Enumeration @enum;
if (pointee.TryGetEnum(out @enum))
if (pointee.TryGetEnum(out var @enum))
{
var isRef = Context.Parameter.Usage == ParameterUsage.Out ||
Context.Parameter.Usage == ParameterUsage.InOut;
@ -455,14 +450,24 @@ namespace CppSharp.Generators.Cpp @@ -455,14 +450,24 @@ namespace CppSharp.Generators.Cpp
return true;
}
Class @class;
if (pointee.TryGetClass(out @class) && @class.IsValueType)
if (pointee.TryGetClass(out var @class) && @class.IsValueType)
{
if (Context.Function == null)
Context.Return.Write("&");
return pointer.QualifiedPointee.Visit(this);
}
if (pointer.IsConstCharString())
{
var genName = Generator.GeneratedIdentifier(Context.Parameter.Name);
Context.Before.WriteLine($"auto {genName} = JS_ToCString(ctx, argv[{Context.ParameterIndex}]);");
Context.Before.WriteLine($"if ({genName} == NULL)");
Context.Before.WriteLineIndent("return JS_EXCEPTION;");
Context.Return.Write($"{genName}");
Context.Cleanup.WriteLine($"JS_FreeCString(ctx, {genName});");
return true;
}
var finalPointee = pointer.GetFinalPointee();
if (finalPointee.IsPrimitiveType())
{
@ -494,6 +499,9 @@ namespace CppSharp.Generators.Cpp @@ -494,6 +499,9 @@ namespace CppSharp.Generators.Cpp
var argName = Context.Parameter.Name;
Context.Before.WriteLine($"{type} {argName};");
(uint width, uint _alignment) =
primitive.GetInfo(Context.Context.TargetInfo, out bool _signed);
switch (primitive)
{
case PrimitiveType.Void:
@ -501,8 +509,6 @@ namespace CppSharp.Generators.Cpp @@ -501,8 +509,6 @@ namespace CppSharp.Generators.Cpp
case PrimitiveType.Bool:
Context.Before.WriteLine($"{argName} = JS_ToBool(ctx, argv[{Context.ParameterIndex}]);");
Context.Before.WriteLine($"if ({argName} == -1)");
Context.Before.WriteLineIndent("return JS_EXCEPTION;");
Context.Return.Write($"{argName}");
return true;
@ -527,31 +533,43 @@ namespace CppSharp.Generators.Cpp @@ -527,31 +533,43 @@ namespace CppSharp.Generators.Cpp
case PrimitiveType.Int:
case PrimitiveType.Long:
if (width == 64)
{
Context.Before.WriteLine($"if (JS_ToBigInt64(ctx, (int64_t*)&{argName}, argv[{Context.ParameterIndex}]))");
Context.Before.WriteLineIndent("return JS_EXCEPTION;");
}
else
{
Context.Before.WriteLine($"if (JS_ToInt32(ctx, &{argName}, argv[{Context.ParameterIndex}]))");
Context.Before.WriteLineIndent("return JS_EXCEPTION;");
}
Context.Return.Write($"{argName}");
return true;
case PrimitiveType.UInt:
case PrimitiveType.ULong:
if (width == 64)
{
Context.Before.WriteLine($"if (JS_ToBigInt64(ctx, (int64_t*)&{argName}, argv[{Context.ParameterIndex}]))");
Context.Before.WriteLineIndent("return JS_EXCEPTION;");
}
else
{
Context.Before.WriteLine($"if (JS_ToUint32(ctx, &{argName}, argv[{Context.ParameterIndex}]))");
Context.Before.WriteLineIndent("return JS_EXCEPTION;");
}
Context.Return.Write($"{argName}");
return true;
case PrimitiveType.LongLong:
Context.Before.WriteLine($"int64_t _{argName};");
Context.Before.WriteLine($"if (JS_ToInt64Ext(ctx, &_{argName}, argv[{Context.ParameterIndex}]))");
Context.Before.WriteLine($"if (JS_ToBigInt64(ctx, (int64_t*)&{argName}, argv[{Context.ParameterIndex}]))");
Context.Before.WriteLineIndent("return JS_EXCEPTION;");
Context.Before.WriteLine($"{argName} = ({type})_{argName};");
Context.Return.Write($"{argName}");
return true;
case PrimitiveType.ULongLong:
Context.Before.WriteLine($"int64_t _{argName};");
Context.Before.WriteLine($"if (JS_ToInt64Ext(ctx, &_{argName}, argv[{Context.ParameterIndex}]))");
Context.Before.WriteLine($"if (JS_ToBigUint64(ctx, (uint64_t*)&{argName}, argv[{Context.ParameterIndex}]))");
Context.Before.WriteLineIndent("return JS_EXCEPTION;");
Context.Before.WriteLine($"{argName} = ({type})_{argName};");
Context.Return.Write($"{argName}");
return true;
@ -569,6 +587,12 @@ namespace CppSharp.Generators.Cpp @@ -569,6 +587,12 @@ namespace CppSharp.Generators.Cpp
Context.Return.Write($"{argName}");
return true;
case PrimitiveType.Null:
Context.Before.WriteLine($"if (!JS_IsNull(argv[{Context.ParameterIndex}]))");
Context.Before.WriteLineIndent("return JS_EXCEPTION;");
Context.Return.Write($"{argName}");
return true;
case PrimitiveType.WideChar:
default:
throw new NotImplementedException();
@ -579,16 +603,14 @@ namespace CppSharp.Generators.Cpp @@ -579,16 +603,14 @@ namespace CppSharp.Generators.Cpp
{
var decl = typedef.Declaration;
TypeMap typeMap;
if (Context.Context.TypeMaps.FindTypeMap(decl.Type, out typeMap) &&
if (Context.Context.TypeMaps.FindTypeMap(decl.Type, out var typeMap) &&
typeMap.DoesMarshalling)
{
typeMap.MarshalToNative(Context);
return typeMap.IsValueType;
}
FunctionType func;
if (decl.Type.IsPointerTo(out func))
if (decl.Type.IsPointerTo(out FunctionType _))
{
typePrinter.PushContext(TypePrinterContextKind.Native);
var declName = decl.Visit(typePrinter);
@ -609,8 +631,7 @@ namespace CppSharp.Generators.Cpp @@ -609,8 +631,7 @@ namespace CppSharp.Generators.Cpp
return true;
}
PrimitiveType primitive;
if (decl.Type.IsPrimitiveType(out primitive))
if (decl.Type.IsPrimitiveType(out _))
{
Context.Return.Write($"(::{typedef.Declaration.QualifiedOriginalName})");
}
@ -621,8 +642,7 @@ namespace CppSharp.Generators.Cpp @@ -621,8 +642,7 @@ namespace CppSharp.Generators.Cpp
public override bool VisitTemplateSpecializationType(TemplateSpecializationType template,
TypeQualifiers quals)
{
TypeMap typeMap;
if (Context.Context.TypeMaps.FindTypeMap(template, out typeMap) && typeMap.DoesMarshalling)
if (Context.Context.TypeMaps.FindTypeMap(template, out var typeMap) && typeMap.DoesMarshalling)
{
typeMap.Type = template;
typeMap.MarshalToNative(Context);
@ -668,42 +688,14 @@ namespace CppSharp.Generators.Cpp @@ -668,42 +688,14 @@ namespace CppSharp.Generators.Cpp
private void MarshalRefClass(Class @class)
{
var type = Context.Parameter.Type.Desugar();
TypeMap typeMap;
if (Context.Context.TypeMaps.FindTypeMap(type, out typeMap) &&
if (Context.Context.TypeMaps.FindTypeMap(type, out var typeMap) &&
typeMap.DoesMarshalling)
{
typeMap.MarshalToNative(Context);
return;
}
if (!type.SkipPointerRefs().IsPointer())
{
Context.Return.Write("*");
if (Context.Parameter.Type.IsReference())
VarPrefix.Write("&");
}
var method = Context.Function as Method;
if (method != null
&& method.Conversion == MethodConversionKind.FunctionToInstanceMethod
&& Context.ParameterIndex == 0)
{
Context.Return.Write($"(::{@class.QualifiedOriginalName}*)");
Context.Return.Write(Helpers.InstanceIdentifier);
return;
}
var paramType = Context.Parameter.Type.Desugar();
var isPointer = paramType.SkipPointerRefs().IsPointer();
var deref = isPointer ? "->" : ".";
var instance = $"(::{@class.QualifiedOriginalName}*)" +
$"{Context.Parameter.Name}{deref}{Helpers.InstanceIdentifier}";
if (isPointer)
Context.Return.Write($"{Context.Parameter.Name} ? {instance} : nullptr");
else
Context.Return.Write($"{instance}");
Context.Return.Write($"({@class.QualifiedOriginalName}*) JS_GetOpaque(argv[{Context.ParameterIndex}], 0)");
}
private void MarshalValueClass(Class @class)

6
src/Generator/Generators/QuickJS/QuickJSModule.cs

@ -30,9 +30,9 @@ namespace CppSharp.Generators.Cpp @@ -30,9 +30,9 @@ namespace CppSharp.Generators.Cpp
{
WriteInclude("CppSharp_QuickJS.h", CInclude.IncludeKind.Angled);
foreach (var unit in TranslationUnits)
WriteInclude(GetIncludeFileName(Context, unit), CInclude.IncludeKind.Quoted);
NewLine();
// foreach (var unit in TranslationUnits)
// WriteInclude(GetIncludeFileName(Context, unit), CInclude.IncludeKind.Quoted);
// NewLine();
}
PopBlock();
NewLine();

58
src/Generator/Generators/QuickJS/QuickJSSources.cs

@ -221,6 +221,11 @@ namespace CppSharp.Generators.Cpp @@ -221,6 +221,11 @@ namespace CppSharp.Generators.Cpp
WriteLine($"JS_CFUNC_DEF(\"{function.Name}\", {maxArgs}, {callbackId}),");
}
public override bool VisitProperty(Property property)
{
return true;
}
public override bool VisitEvent(Event @event)
{
var getterId = $"callback_event_getter_{GetCIdentifier(Context, @event)}";
@ -301,8 +306,9 @@ namespace CppSharp.Generators.Cpp @@ -301,8 +306,9 @@ namespace CppSharp.Generators.Cpp
}
else
{
var classId = $"classId_{GetCIdentifier(Context, @class)}";
Write($"{@class.QualifiedOriginalName}* instance = ");
WriteLine($"({@class.QualifiedOriginalName}*) JS_GetOpaque(val, 0);");
WriteLine($"({@class.QualifiedOriginalName}*) JS_GetOpaque(val, {classId});");
}
UnindentAndWriteCloseBrace();
@ -311,10 +317,10 @@ namespace CppSharp.Generators.Cpp @@ -311,10 +317,10 @@ namespace CppSharp.Generators.Cpp
PushBlock();
{
WriteLine($"static JSClassDef classDef_{GetCIdentifier(Context, @class)}");
WriteLine($"static JSClassDef classDef_{GetCIdentifier(Context, @class)} =");
WriteOpenBraceAndIndent();
WriteLine($"\"{@class.Name}\",");
WriteLine($".class_name = \"{@class.Name}\",");
WriteLine($".finalizer = {finalizerId}");
Unindent();
@ -324,7 +330,7 @@ namespace CppSharp.Generators.Cpp @@ -324,7 +330,7 @@ namespace CppSharp.Generators.Cpp
PushBlock();
{
WriteLine($"static JSCFunctionListEntry funcDef_{GetCIdentifier(Context, @class)}[]");
WriteLine($"static JSCFunctionListEntry funcDef_{GetCIdentifier(Context, @class)}[] =");
WriteOpenBraceAndIndent();
var funcGen = new QuickJSClassFuncDef(Context);
@ -412,17 +418,14 @@ namespace CppSharp.Generators.Cpp @@ -412,17 +418,14 @@ namespace CppSharp.Generators.Cpp
WriteLine($"JSValue event = JS_Interop_FindEvent(&events, {@event.GlobalId});");
WriteLine($"if (JS_IsUndefined(event))");
var defaultValuePrinter = new CppDefaultValuePrinter(Context);
var defaultValue = functionType.ReturnType.Visit(defaultValuePrinter);
var isVoidReturn = functionType.ReturnType.Type.IsPrimitiveType(PrimitiveType.Void);
if (isVoidReturn)
{
WriteLineIndent($"return;");
}
else
{
var defaultValuePrinter = new CppDefaultValuePrinter(Context);
var defaultValue = functionType.ReturnType.Visit(defaultValuePrinter);
WriteLineIndent($"return {defaultValue};");
}
NewLine();
// Marshal the arguments.
@ -450,25 +453,14 @@ namespace CppSharp.Generators.Cpp @@ -450,25 +453,14 @@ namespace CppSharp.Generators.Cpp
var args = marshalers.Select(m => m.Context.Return.ToString());
WriteLine($"JSValueConst argv[] = {{ { string.Join(", ", args)} }};");
WriteLine($"auto data = (JS_SignalContext*) JS_GetOpaque(event, 0);");
WriteLine($"auto data = (JS_SignalContext*) JS_GetOpaque(event, {QuickJSSources.SignalClassId});");
WriteLine($"JSValue ret = JS_Call(ctx, data->function, JS_UNDEFINED, {@event.Parameters.Count}, argv);");
WriteLine($"JS_FreeValue(ctx, ret);");
//WriteLine($"{@class.QualifiedOriginalName}* instance = data->instance;");
/*
if (!isVoidReturn)
{
CTypePrinter.PushContext(TypePrinterContextKind.Native);
var returnType = function.ReturnType.Visit(CTypePrinter);
CTypePrinter.PopContext();
Write($"{returnType} {Helpers.ReturnIdentifier} = ");
}
var @class = function.Namespace as Class;
*/
if (isVoidReturn)
WriteLineIndent($"return;");
else
WriteLineIndent($"return {defaultValue};");
UnindentAndWriteCloseBrace();
}
@ -594,7 +586,7 @@ namespace CppSharp.Generators.Cpp @@ -594,7 +586,7 @@ namespace CppSharp.Generators.Cpp
WriteLine("if (phase == 0)");
WriteOpenBraceAndIndent();
{
WriteLine($"JS_NewClassID(&{classId});");
WriteLine($"JS_NewClassID(JS_GetRuntime(ctx), &{classId});");
NewLine();
WriteLine($"JS_NewClass(JS_GetRuntime(ctx), {classId}, &{classDef});");
@ -786,13 +778,15 @@ namespace CppSharp.Generators.Cpp @@ -786,13 +778,15 @@ namespace CppSharp.Generators.Cpp
else if (QuickJSRegister.ClassNeedsExtraData(@class))
{
var classDataId = $"data_{GetCIdentifier(Context, @class)}";
WriteLine($"auto data = ({classDataId}*) JS_GetOpaque(this_val, 0);");
WriteLine("JSClassID _dummy;");
WriteLine($"auto data = ({classDataId}*) JS_GetAnyOpaque(this_val, &_dummy);");
WriteLine($"{@class.QualifiedOriginalName}* instance = ({@class.QualifiedOriginalName}*) data->instance;");
}
else
{
WriteLine("JSClassID _dummy;");
Write($"{@class.QualifiedOriginalName}* instance = ");
WriteLine($"({@class.QualifiedOriginalName}*) JS_GetOpaque(this_val, 0);");
WriteLine($"({@class.QualifiedOriginalName}*) JS_GetAnyOpaque(this_val, &_dummy);");
}
NewLine();
@ -912,7 +906,7 @@ namespace CppSharp.Generators.Cpp @@ -912,7 +906,7 @@ namespace CppSharp.Generators.Cpp
public override string GenerateTypeCheckForParameter(int paramIndex, Type type)
{
var typeChecker = new QuickJSTypeCheckGen(paramIndex);
var typeChecker = new QuickJSTypeCheckGen(Context, paramIndex);
type.Visit(typeChecker);
var condition = typeChecker.Generate();
@ -931,9 +925,9 @@ namespace CppSharp.Generators.Cpp @@ -931,9 +925,9 @@ namespace CppSharp.Generators.Cpp
WriteOpenBraceAndIndent();
var @class = @event.Namespace as Class;
var classId = $"classId_{GetCIdentifier(Context, @class)}";
var classDataId = $"data_{GetCIdentifier(Context, @class)}";
WriteLine($"auto data = ({classDataId}*) JS_GetOpaque(this_val, 0);");
WriteLine("JSClassID _dummy;");
WriteLine($"auto data = ({classDataId}*) JS_GetAnyOpaque(this_val, &_dummy);");
WriteLine($"if (data == nullptr)");
WriteLineIndent("return JS_ThrowTypeError(ctx, \"Could not find object instance\");");

11
src/Generator/Generators/QuickJS/QuickJSTypeCheckGen.cs

@ -11,7 +11,7 @@ namespace CppSharp.Generators.Cpp @@ -11,7 +11,7 @@ namespace CppSharp.Generators.Cpp
public override string FileExtension { get; }
public QuickJSTypeCheckGen(int parameterIndex) : base(null)
public QuickJSTypeCheckGen(BindingContext context, int parameterIndex) : base(context)
{
ParameterIndex = parameterIndex;
}
@ -23,7 +23,8 @@ namespace CppSharp.Generators.Cpp @@ -23,7 +23,8 @@ namespace CppSharp.Generators.Cpp
public override bool VisitPrimitiveType(PrimitiveType primitive, TypeQualifiers quals)
{
// TODO: Use TargetInfo to check the actual width of types for the target.
(uint width, uint _alignment) =
primitive.GetInfo(Context.TargetInfo, out bool _signed);
var condition = string.Empty;
var arg = $"argv[{ParameterIndex}]";
@ -50,10 +51,16 @@ namespace CppSharp.Generators.Cpp @@ -50,10 +51,16 @@ namespace CppSharp.Generators.Cpp
break;
case PrimitiveType.Int:
case PrimitiveType.Long:
if (width == 64)
condition = $"JS_IsBigInt(ctx, {arg})";
else
condition = $"JS_IsInt32({arg})";
break;
case PrimitiveType.ULong:
case PrimitiveType.UInt:
if (width == 64)
condition = $"JS_IsBigInt(ctx, {arg})";
else
condition = $"JS_IsUInt32({arg})";
break;
case PrimitiveType.LongLong:

10
src/Generator/Generators/QuickJS/Runtime/CppSharp_QuickJS.h

@ -174,10 +174,18 @@ static JSValue JS_Interop_CleanupObject(JSValue obj, JS_Interop_InstanceKind kin @@ -174,10 +174,18 @@ static JSValue JS_Interop_CleanupObject(JSValue obj, JS_Interop_InstanceKind kin
switch (kind)
{
case JS_INTEROP_INSTANCE_SIGNAL_CONTEXT:
JS_Interop_ClassData* data = (JS_Interop_ClassData*) JS_GetOpaque(obj, 0);
{
JS_Interop_ClassData* data = (JS_Interop_ClassData*) JS_GetOpaque(obj, JS_GetClassID(obj));
if (data)
{
JS_Interop_FreeEventMap(data->ctx, &data->events);
js_free(data->ctx, data);
}
break;
}
case JS_INTEROP_INSTANCE_RAW_POINTER:
break;
}
return JS_UNDEFINED;
}

18
src/Generator/Generators/QuickJS/Runtime/Signal.cpp → src/Generator/Generators/QuickJS/Runtime/CppSharp_QuickJS_Signal.cpp

@ -4,6 +4,7 @@ @@ -4,6 +4,7 @@
// Do not edit this file or all your changes will be lost after re-generation.
// </auto-generated>
// ----------------------------------------------------------------------------
#include "quickjs.h"
#include <CppSharp_QuickJS.h>
#include <assert.h>
@ -67,7 +68,7 @@ static JSValue callback_method_Signal_connect(JSContext* ctx, JSValueConst this_ @@ -67,7 +68,7 @@ static JSValue callback_method_Signal_connect(JSContext* ctx, JSValueConst this_
// Connect logic
auto signalCtx = (JS_SignalContext*) JS_GetOpaque(this_val, classId__Signal);
JS_SignalContext* signalCtx = (JS_SignalContext*) JS_GetOpaque(this_val, classId__Signal);
if (signalCtx == nullptr)
return JS_ThrowTypeError(ctx, "Could not find signal context");
@ -127,7 +128,7 @@ static JSValue callback_method_Signal_isEmpty(JSContext* ctx, JSValueConst this_ @@ -127,7 +128,7 @@ static JSValue callback_method_Signal_isEmpty(JSContext* ctx, JSValueConst this_
return JS_ThrowRangeError(ctx, "Unsupported number of arguments");
}
auto signalCtx = (JS_SignalContext*) JS_GetOpaque(this_val, classId__Signal);
JS_SignalContext* signalCtx = (JS_SignalContext*) JS_GetOpaque(this_val, classId__Signal);
JSValue ____ret = JS_NewBool(ctx, JS_IsUndefined(signalCtx->function));
@ -142,26 +143,25 @@ static JSValue callback_class__Signal_toString(JSContext* ctx, JSValueConst this @@ -142,26 +143,25 @@ static JSValue callback_class__Signal_toString(JSContext* ctx, JSValueConst this
void finalizer__Signal(JSRuntime *rt, JSValue val)
{
auto signalCtx = (JS_SignalContext*) JS_GetOpaque(val, classId__Signal);
JS_SignalContext* signalCtx = (JS_SignalContext*) JS_GetOpaque(val, classId__Signal);
if (signalCtx == nullptr)
return;
if (!JS_IsUndefined(signalCtx->function))
return JS_FreeValue(signalCtx->ctx, signalCtx->function);
delete signalCtx;
js_free_rt(rt, signalCtx);
JS_SetOpaque(val, nullptr);
}
static JSClassDef classDef__Signal
static JSClassDef classDef__Signal =
{
"Signal",
.class_name = "Signal",
.finalizer = finalizer__Signal
};
static JSCFunctionListEntry funcDef__Signal[]
static JSCFunctionListEntry funcDef__Signal[] =
{
JS_CFUNC_DEF("connect", 1, callback_method_Signal_connect),
JS_CFUNC_DEF("disconnect", 1, callback_method_Signal_disconnect),
@ -179,7 +179,7 @@ static void register_class__Signal(JSContext *ctx, JSModuleDef *m, bool set, int @@ -179,7 +179,7 @@ static void register_class__Signal(JSContext *ctx, JSModuleDef *m, bool set, int
if (phase == 0)
{
JS_NewClassID(&classId__Signal);
JS_NewClassID(JS_GetRuntime(ctx), &classId__Signal);
JS_NewClass(JS_GetRuntime(ctx), classId__Signal, &classDef__Signal);

0
src/Generator/Generators/QuickJS/Runtime/Signal.h → src/Generator/Generators/QuickJS/Runtime/CppSharp_QuickJS_Signal.h

3
src/Generator/Options.cs

@ -276,6 +276,9 @@ namespace CppSharp @@ -276,6 +276,9 @@ namespace CppSharp
/// </summary>
public HashSet<string> ExplicitlyPatchedVirtualFunctions { get; }
public PropertyDetectionMode PropertyDetectionMode { get; set; } = PropertyDetectionMode.Dictionary;
[Obsolete("Use PropertyDetectionMode instead")]
public bool UsePropertyDetectionHeuristics { get; set; } = true;
/// <summary>

94
src/Generator/Passes/GetterSetterToPropertyPass.cs

@ -11,6 +11,33 @@ using Type = CppSharp.AST.Type; @@ -11,6 +11,33 @@ using Type = CppSharp.AST.Type;
namespace CppSharp.Passes
{
/// <summary>
/// This is used by GetterSetterToPropertyPass to decide how to process
/// getter/setter class methods into properties.
/// </summary>
public enum PropertyDetectionMode
{
/// <summary>
/// No methods are converted to properties.
/// </summary>
None,
/// <summary>
/// All compatible methods are converted to properties.
/// </summary>
All,
/// <summary>
/// Only methods starting with certain keyword are converted to properties.
/// Right now we consider getter methods starting with "get", "is" and "has".
/// </summary>
Keywords,
/// <summary>
/// Heuristics based mode that uses english dictionary words to decide
/// if a getter method is an action and thus not to be considered as a
/// property.
/// </summary>
Dictionary
}
public class GetterSetterToPropertyPass : TranslationUnitPass
{
static GetterSetterToPropertyPass()
@ -44,6 +71,9 @@ namespace CppSharp.Passes @@ -44,6 +71,9 @@ namespace CppSharp.Passes
public override bool VisitClassDecl(Class @class)
{
if (Options.PropertyDetectionMode == PropertyDetectionMode.None)
return false;
if (!base.VisitClassDecl(@class))
return false;
@ -86,35 +116,58 @@ namespace CppSharp.Passes @@ -86,35 +116,58 @@ namespace CppSharp.Passes
private IEnumerable<Property> CleanUp(Class @class, List<Property> properties)
{
if (!Options.UsePropertyDetectionHeuristics)
#pragma warning disable CS0618
if (!Options.UsePropertyDetectionHeuristics ||
#pragma warning restore CS0618
Options.PropertyDetectionMode == PropertyDetectionMode.All)
return properties;
for (int i = properties.Count - 1; i >= 0; i--)
{
Property property = properties[i];
if (property.HasSetter || property.IsExplicitlyGenerated)
continue;
string firstWord = GetFirstWord(property.GetMethod.Name);
if (firstWord.Length < property.GetMethod.Name.Length &&
Match(firstWord, new[] { "get", "is", "has" }))
var property = properties[i];
if (KeepProperty(property))
continue;
if (Match(firstWord, new[] { "to", "new", "on" }) ||
Verbs.Contains(firstWord))
{
property.GetMethod.GenerationKind = GenerationKind.Generate;
@class.Properties.Remove(property);
properties.RemoveAt(i);
}
}
return properties;
}
public virtual bool KeepProperty(Property property)
{
if (property.HasSetter || property.IsExplicitlyGenerated)
return true;
var firstWord = GetFirstWord(property.GetMethod.Name);
var isKeyword = firstWord.Length < property.GetMethod.Name.Length &&
Match(firstWord, new[] {"get", "is", "has"});
switch (Options.PropertyDetectionMode)
{
case PropertyDetectionMode.Keywords:
return isKeyword;
case PropertyDetectionMode.Dictionary:
var isAction = Match(firstWord, new[] {"to", "new", "on"}) || Verbs.Contains(firstWord);
return isKeyword || !isAction;
default:
return false;
}
}
private static void CreateOrUpdateProperty(List<Property> properties, Method method,
string name, QualifiedType type, bool isSetter = false)
{
string NormalizeName(string name)
{
return string.IsNullOrEmpty(name) ?
name : string.Concat(char.ToLowerInvariant(name[0]), name.Substring(1));
}
var normalizedName = NormalizeName(name);
Type underlyingType = GetUnderlyingType(type);
Property property = properties.Find(
p => p.Field == null &&
@ -124,10 +177,10 @@ namespace CppSharp.Passes @@ -124,10 +177,10 @@ namespace CppSharp.Passes
p.GetMethod.OriginalReturnType).Equals(underlyingType)) ||
(p.HasSetter && GetUnderlyingType(
p.SetMethod.Parameters[0].QualifiedType).Equals(underlyingType))) &&
Match(p, name));
Match(p, normalizedName));
if (property == null)
properties.Add(property = new Property { Name = name, QualifiedType = type });
properties.Add(property = new Property { Name = normalizedName, QualifiedType = type });
method.AssociatedDeclaration = property;
@ -201,7 +254,9 @@ namespace CppSharp.Passes @@ -201,7 +254,9 @@ namespace CppSharp.Passes
property.SetMethod.OriginalReturnType.Type.Desugar().IsPrimitiveType(PrimitiveType.Void))
property.SetMethod.GenerationKind = GenerationKind.Internal;
property.Namespace = @class;
@class.Properties.Add(property);
RenameConflictingMethods(@class, property);
CombineComments(property);
}
@ -294,14 +349,8 @@ namespace CppSharp.Passes @@ -294,14 +349,8 @@ namespace CppSharp.Passes
(string.Compare(name, firstWord, StringComparison.InvariantCultureIgnoreCase) == 0) ||
char.IsNumber(name[3])) return name;
if (name.Length == 4)
{
return char.ToLowerInvariant(
name[3]).ToString(CultureInfo.InvariantCulture);
}
return string.Concat(char.ToLowerInvariant(
name[3]).ToString(CultureInfo.InvariantCulture), name.AsSpan(4));
var rest = (name.Length == 4) ? string.Empty : name.Substring(4);
return string.Concat(name[3], rest);
}
private static string GetPropertyNameFromSetter(string name)
@ -314,7 +363,6 @@ namespace CppSharp.Passes @@ -314,7 +363,6 @@ namespace CppSharp.Passes
return nameBuilder.ToString();
nameBuilder.TrimUnderscores();
nameBuilder[0] = char.ToLowerInvariant(nameBuilder[0]);
return nameBuilder.ToString();
}

2
tests/Builtins.h

@ -1,3 +1,5 @@ @@ -1,3 +1,5 @@
#pragma once
#include <cstddef>
#include <cstdint>

8
tests/Classes.h

@ -1,3 +1,5 @@ @@ -1,3 +1,5 @@
#pragma once
#include "Classes2.h"
class Class
@ -5,7 +7,7 @@ class Class @@ -5,7 +7,7 @@ class Class
public:
void ReturnsVoid() {}
int ReturnsInt() { return 0; }
Class* PassAndReturnsClassPtr(Class* obj) { return obj; }
// Class* PassAndReturnsClassPtr(Class* obj) { return obj; }
};
class ClassWithField
@ -36,5 +38,5 @@ class ClassWithExternalInheritance : public ClassFromAnotherUnit @@ -36,5 +38,5 @@ class ClassWithExternalInheritance : public ClassFromAnotherUnit
};
void FunctionPassClassByRef(Class* klass) { }
Class* FunctionReturnsClassByRef() { return new Class(); }
//void FunctionPassClassByRef(Class* klass) { }
//Class* FunctionReturnsClassByRef() { return new Class(); }

2
tests/Classes2.h

@ -1,3 +1,5 @@ @@ -1,3 +1,5 @@
#pragma once
class ClassFromAnotherUnit
{

3
tests/Delegates.h

@ -1,3 +1,5 @@ @@ -1,3 +1,5 @@
#pragma once
#include <FastDelegates.h>
using namespace fastdelegate;
@ -5,6 +7,7 @@ using namespace fastdelegate; @@ -5,6 +7,7 @@ using namespace fastdelegate;
class ClassWithDelegate
{
public:
ClassWithDelegate() {}
FastDelegate<int(int)> OnEvent0;
void FireEvent0(int value) { if (OnEvent0) OnEvent0(value); }
};

2
tests/Enums.h

@ -1,3 +1,5 @@ @@ -1,3 +1,5 @@
#pragma once
enum class Enum0
{
Item0,

2
tests/Overloads.h

@ -1,3 +1,5 @@ @@ -1,3 +1,5 @@
#pragma once
void Overload0() {}
int Overload1() { return 1; }

1
tests/emscripten/premake5.lua

@ -4,6 +4,7 @@ workspace "emscripten" @@ -4,6 +4,7 @@ workspace "emscripten"
location "gen"
symbols "On"
optimize "Off"
cppdialect "C++14"
project "test"
kind "SharedLib"

39
tests/emscripten/test.mjs

@ -1,11 +1,14 @@ @@ -1,11 +1,14 @@
import wasmModule from "./gen/bin/debug/libtest.mjs";
import { eq, ascii, floateq } from "./utils.mjs"
const test = await wasmModule({
onRuntimeInitialized() {
const test = await wasmModule({ onRuntimeInitialized() {} });
const features = {
// https://github.com/WebAssembly/proposals/issues/7
// https://github.com/emscripten-core/emscripten/issues/11140
supportsInt64: false,
supportsNull: false,
}
});
function builtins() {
eq(test.ReturnsVoid(), undefined)
@ -13,8 +16,10 @@ function builtins() { @@ -13,8 +16,10 @@ function builtins() {
eq(test.ReturnsBool(), true)
eq(test.PassAndReturnsBool(false), false)
if (features.supportsNull) {
eq(test.ReturnsNullptr(), null)
eq(test.PassAndReturnsNullptr(null), null)
}
eq(test.ReturnsChar(), ascii('a'));
eq(test.ReturnsSChar(), ascii('a'));
@ -41,11 +46,10 @@ function builtins() { @@ -41,11 +46,10 @@ function builtins() {
eq(test.ReturnsInt32(), -5);
eq(test.ReturnsUInt32(), 5);
// TODO:
// https://github.com/WebAssembly/proposals/issues/7
// https://github.com/emscripten-core/emscripten/issues/11140
//eq(test.ReturnsInt64(), -5n);
//eq(test.ReturnsUInt64(), 5n);
if (features.supportsInt64) {
eq(test.ReturnsInt64(), -5n);
eq(test.ReturnsUInt64(), 5n);
}
const int8 = { min: -(2 ** 7), max: (2 ** 7) - 1 };
eq(test.PassAndReturnsInt8(int8.min), int8.min);
@ -71,13 +75,15 @@ function builtins() { @@ -71,13 +75,15 @@ function builtins() {
eq(test.PassAndReturnsUInt32(uint32.min), uint32.min);
eq(test.PassAndReturnsUInt32(uint32.max), uint32.max);
//const int64 = { min: BigInt(2 ** 63) * -1n, max: BigInt(2 ** 63) - 1n };
//eq(test.PassAndReturnsInt64(int64.min), int64.min);
//eq(test.PassAndReturnsInt64(int64.max), int64.max);
if (features.supportsInt64) {
const int64 = { min: BigInt(2 ** 63) * -1n, max: BigInt(2 ** 63) - 1n };
eq(test.PassAndReturnsInt64(int64.min), int64.min);
eq(test.PassAndReturnsInt64(int64.max), int64.max)
//const uint64 = { min: BigInt(0), max: BigInt(2 ** 64) - 1n };
//eq(test.PassAndReturnsUInt64(uint64.min), uint64.min);
//eq(test.PassAndReturnsUInt64(uint64.max), uint64.max);
const uint64 = { min: BigInt(0), max: BigInt(2 ** 64) - 1n };
eq(test.PassAndReturnsUInt64(uint64.min), uint64.min);
eq(test.PassAndReturnsUInt64(uint64.max), uint64.max);
}
}
function enums() {
@ -94,7 +100,7 @@ function classes() { @@ -94,7 +100,7 @@ function classes() {
eq(typeof (c), "object")
eq(c.ReturnsVoid(), undefined)
eq(c.ReturnsInt(), 0)
eq(c.PassAndReturnsClassPtr(null), null)
//eq(c.PassAndReturnsClassPtr(null), null)
var c1 = new test.ClassWithSingleInheritance();
eq(c1.__proto__.constructor.name, 'ClassWithSingleInheritance')
@ -105,10 +111,9 @@ function classes() { @@ -105,10 +111,9 @@ function classes() {
var classWithField = new test.ClassWithField();
eq(classWithField.ReturnsField(), 10);
eq(classWithField.Field, 10);
//eq(classWithField.Field, 10);
}
builtins();
enums();
classes();

19
tests/emscripten/test.sh

@ -5,17 +5,32 @@ rootdir="$dir/../.." @@ -5,17 +5,32 @@ rootdir="$dir/../.."
dotnet_configuration=Release
configuration=debug
platform=x64
jsinterp=node
jsinterp=$(which node)
for arg in "$@"; do
case $arg in
--with-node=*)
jsinterp="${arg#*=}"
shift
;;
esac
done
if [ "$CI" = "true" ]; then
red=""
green=""
reset=""
else
red=`tput setaf 1`
green=`tput setaf 2`
reset=`tput sgr0`
fi
generate=true
if [ $generate = true ]; then
echo "${green}Generating bindings${reset}"
dotnet $rootdir/bin/${dotnet_configuration}_${platform}/CppSharp.CLI.dll \
dotnet $rootdir/bin/${dotnet_configuration}/CppSharp.CLI.dll \
--gen=emscripten --platform=emscripten --arch=wasm32 \
-I$dir/.. -I$rootdir/include -o $dir/gen -m tests $dir/../*.h
fi

8
tests/napi/test.sh

@ -5,12 +5,18 @@ rootdir="$dir/../.." @@ -5,12 +5,18 @@ rootdir="$dir/../.."
configuration=Release
platform=x64
if [ "$CI" = "true" ]; then
red=""
green=""
reset=""
else
red=`tput setaf 1`
green=`tput setaf 2`
reset=`tput sgr0`
fi
echo "${green}Generating bindings${reset}"
dotnet $rootdir/bin/${configuration}_${platform}/CppSharp.CLI.dll \
dotnet $rootdir/bin/${configuration}/CppSharp.CLI.dll \
--gen=napi -I$dir/.. -o $dir/gen -m tests $dir/../*.h
echo "${green}Building generated binding files${reset}"

3
tests/quickjs/.gitignore vendored

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
gen
runtime/
gen/
*.so
*.dylib
*.dll

22
tests/quickjs/bindings.lua

@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
generator "quickjs"
architecture "x64"
includedirs
{
"..",
"../../include",
}
output "gen"
module "test"
namespace "test"
headers
{
"Builtins.h",
"Classes.h",
"Classes2.h",
"Delegates.h",
"Enums.h",
"Overloads.h"
}

15
tests/quickjs/bootstrap.sh

@ -0,0 +1,15 @@ @@ -0,0 +1,15 @@
#!/usr/bin/env bash
set -e
dir=$(cd "$(dirname "$0")"; pwd)
rootdir="$dir/../.."
cd $dir
if [ ! -d runtime ]; then
git clone https://github.com/quickjs-ng/quickjs.git runtime
git -C runtime reset --hard 0e5e9c2c49db15ab9579edeb4d90e610c8b8463f
fi
if [ ! -f runtime/build/qjs ]; then
make -C runtime/
fi

13
tests/quickjs/premake5.lua

@ -1,5 +1,4 @@ @@ -1,5 +1,4 @@
local qjs_dir = path.getabsolute("../../deps/quickjs")
local runtime = "../../src/Generator/Generators/QuickJS/Runtime"
local cppsharp_qjs_runtime = "../../src/Generator/Generators/QuickJS/Runtime"
workspace "qjs"
configurations { "debug", "release" }
@ -10,16 +9,17 @@ workspace "qjs" @@ -10,16 +9,17 @@ workspace "qjs"
project "test"
kind "SharedLib"
language "C++"
cppdialect "C++11"
files
{
"gen/**.cpp",
runtime .. "/*.cpp",
runtime .. "/*.c"
cppsharp_qjs_runtime .. "/*.cpp",
cppsharp_qjs_runtime .. "/*.c"
}
includedirs
{
qjs_dir,
runtime,
"runtime",
cppsharp_qjs_runtime,
"..",
"../../include"
}
@ -30,3 +30,4 @@ workspace "qjs" @@ -30,3 +30,4 @@ workspace "qjs"
defines { "JS_SHARED_LIBRARY" }
filter { "kind:SharedLib", "system:macosx" }
linkoptions { "-undefined dynamic_lookup" }
targetextension (".so")

10
tests/quickjs/test.js

@ -129,18 +129,18 @@ function classes() @@ -129,18 +129,18 @@ function classes()
var c = new test.Class();
eq(typeof(c), "object")
eq(c.ReturnsVoid(), undefined)
eq(c.ReturnsInt(), 0)
eq(c.PassAndReturnsClassPtr(null), null)
//eq(c.ReturnsInt(), 0)
//eq(c.PassAndReturnsClassPtr(null), null)
var c1 = new test.ClassWithSingleInheritance();
eq(c1.__proto__.constructor.name, 'ClassWithSingleInheritance')
eq(c1.__proto__.__proto__.constructor.name, 'Class')
eq(c1.ReturnsVoid(), undefined);
eq(c1.ReturnsInt(), 0);
eq(c1.ChildMethod(), 2);
//eq(c1.ReturnsInt(), 0);
//eq(c1.ChildMethod(), 2);
var classWithField = new test.ClassWithField();
eq(classWithField.ReturnsField(), 10);
//eq(classWithField.ReturnsField(), 10);
}
function delegates()

20
tests/quickjs/test.sh

@ -4,28 +4,34 @@ dir=$(cd "$(dirname "$0")"; pwd) @@ -4,28 +4,34 @@ dir=$(cd "$(dirname "$0")"; pwd)
rootdir="$dir/../.."
dotnet_configuration=Release
configuration=debug
platform=x64
jsinterp="$rootdir/deps/quickjs/qjs-debug"
jsinterp="$dir/runtime/build/qjs"
cd $dir
if [ "$CI" = "true" ]; then
red=""
green=""
reset=""
else
red=`tput setaf 1`
green=`tput setaf 2`
reset=`tput sgr0`
fi
generate=true
if [ $generate = true ]; then
echo "${green}Generating bindings${reset}"
dotnet $rootdir/bin/${dotnet_configuration}_${platform}/CppSharp.CLI.dll \
--gen=qjs -I$dir/.. -I$rootdir/include -o $dir/gen -m tests $dir/../*.h
dotnet $rootdir/bin/${dotnet_configuration}/CppSharp.CLI.dll \
$dir/bindings.lua
fi
echo "${green}Building generated binding files${reset}"
premake=$rootdir/build/premake.sh
config=$configuration $premake --file=$dir/premake5.lua gmake
make -C $dir/gen
config=$configuration $premake --file=$dir/premake5.lua gmake2
verbose=true make -C $dir/gen
echo
echo "${green}Executing JS tests with QuickJS${reset}"
cp $dir/gen/bin/$configuration/libtest.so $dir
#cp $dir/gen/bin/$configuration/libtest.dylib $dir
$jsinterp --std $dir/test.js

8
tests/ts/test.sh

@ -7,15 +7,21 @@ configuration=debug @@ -7,15 +7,21 @@ configuration=debug
platform=x64
jsinterp="$rootdir/deps/quickjs/qjs-debug"
if [ "$CI" = "true" ]; then
red=""
green=""
reset=""
else
red=`tput setaf 1`
green=`tput setaf 2`
reset=`tput sgr0`
fi
generate=true
if [ $generate = true ]; then
echo "${green}Generating bindings${reset}"
dotnet $rootdir/bin/${dotnet_configuration}_${platform}/CppSharp.CLI.dll \
dotnet $rootdir/bin/${dotnet_configuration}/CppSharp.CLI.dll \
--gen=ts -I$dir/.. -I$rootdir/include -o $dir/gen -m tests $dir/../*.h
fi

Loading…
Cancel
Save