diff --git a/packages/Avalonia/AvaloniaBuildTasks.targets b/packages/Avalonia/AvaloniaBuildTasks.targets index 57b4cb04e3..45a7f1aa44 100644 --- a/packages/Avalonia/AvaloniaBuildTasks.targets +++ b/packages/Avalonia/AvaloniaBuildTasks.targets @@ -4,6 +4,7 @@ <_AvaloniaUseExternalMSBuild Condition="'$(_AvaloniaForceInternalMSBuild)' == 'true'">false low <_AvaloniaPatchComInterop Condition="'$(_AvaloniaPatchComInterop)' == ''">false + <_AvaloniaSkipXamlCompilation Condition="'$(_AvaloniaSkipXamlCompilation)' == ''">false @@ -92,6 +93,7 @@ SignAssembly="$(SignAssembly)" DelaySign="$(DelaySign)" EnableComInteropPatching="$(_AvaloniaPatchComInterop)" + SkipXamlCompilation="$(_AvaloniaSkipXamlCompilation)" /> !string.IsNullOrWhiteSpace(l)).ToArray(), ProjectDirectory, OutputPath, VerifyIl, outputImportance, (SignAssembly && !DelaySign) ? AssemblyOriginatorKeyFile : null, - EnableComInteropPatching); + EnableComInteropPatching, SkipXamlCompilation); if (!res.Success) return false; if (!res.WrittenFile) @@ -77,6 +77,7 @@ namespace Avalonia.Build.Tasks public bool VerifyIl { get; set; } public bool EnableComInteropPatching { get; set; } + public bool SkipXamlCompilation { get; set; } public string AssemblyOriginatorKeyFile { get; set; } public bool SignAssembly { get; set; } diff --git a/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs b/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs index 938732cfe1..0b9b50e771 100644 --- a/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs +++ b/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs @@ -40,17 +40,48 @@ namespace Avalonia.Build.Tasks WrittenFile = writtenFile; } } + + public static CompileResult Compile(IBuildEngine engine, string input, string[] references, + string projectDirectory, + string output, bool verifyIl, MessageImportance logImportance, string strongNameKey, bool patchCom, + bool skipXamlCompilation) + { + var typeSystem = new CecilTypeSystem(references.Concat(new[] { input }), input); + + var asm = typeSystem.TargetAssemblyDefinition; + + if (!skipXamlCompilation) + { + var compileRes = CompileCore(engine, typeSystem, projectDirectory, verifyIl, logImportance); + if (compileRes == null && !patchCom) + return new CompileResult(true); + if (compileRes == false) + return new CompileResult(false); + } + + if (patchCom) + ComInteropHelper.PatchAssembly(asm, typeSystem); + + var writerParameters = new WriterParameters { WriteSymbols = asm.MainModule.HasSymbols }; + if (!string.IsNullOrWhiteSpace(strongNameKey)) + writerParameters.StrongNameKeyBlob = File.ReadAllBytes(strongNameKey); + + asm.Write(output, writerParameters); + + return new CompileResult(true, true); + + } - public static CompileResult Compile(IBuildEngine engine, string input, string[] references, string projectDirectory, - string output, bool verifyIl, MessageImportance logImportance, string strongNameKey, bool patchCom) + static bool? CompileCore(IBuildEngine engine, CecilTypeSystem typeSystem, + string projectDirectory, bool verifyIl, + MessageImportance logImportance) { - var typeSystem = new CecilTypeSystem(references.Concat(new[] {input}), input); var asm = typeSystem.TargetAssemblyDefinition; var emres = new EmbeddedResources(asm); var avares = new AvaloniaResources(asm, projectDirectory); - if (avares.Resources.Count(CheckXamlName) == 0 && emres.Resources.Count(CheckXamlName) == 0 && !patchCom) + if (avares.Resources.Count(CheckXamlName) == 0 && emres.Resources.Count(CheckXamlName) == 0) // Nothing to do - return new CompileResult(true); + return null; var clrPropertiesDef = new TypeDefinition("CompiledAvaloniaXaml", "XamlIlHelpers", TypeAttributes.Class, asm.MainModule.TypeSystem.Object); @@ -364,27 +395,17 @@ namespace Avalonia.Build.Tasks if (emres.Resources.Count(CheckXamlName) != 0) if (!CompileGroup(emres)) - return new CompileResult(false); + return false; if (avares.Resources.Count(CheckXamlName) != 0) { if (!CompileGroup(avares)) - return new CompileResult(false); + return false; avares.Save(); } loaderDispatcherMethod.Body.Instructions.Add(Instruction.Create(OpCodes.Ldnull)); loaderDispatcherMethod.Body.Instructions.Add(Instruction.Create(OpCodes.Ret)); - - if (patchCom) - ComInteropHelper.PatchAssembly(asm, typeSystem); - - var writerParameters = new WriterParameters { WriteSymbols = asm.MainModule.HasSymbols }; - if (!string.IsNullOrWhiteSpace(strongNameKey)) - writerParameters.StrongNameKeyBlob = File.ReadAllBytes(strongNameKey); - - asm.Write(output, writerParameters); - - return new CompileResult(true, true); + return true; } } diff --git a/src/Avalonia.MicroCom/Avalonia.MicroCom.csproj b/src/Avalonia.MicroCom/Avalonia.MicroCom.csproj index aaf54ed80e..7994a74f76 100644 --- a/src/Avalonia.MicroCom/Avalonia.MicroCom.csproj +++ b/src/Avalonia.MicroCom/Avalonia.MicroCom.csproj @@ -1,8 +1,10 @@ - - - netstandard2.0 - true - - + + netstandard2.0 + true + + + <_AvaloniaPatchComInterop>true + + diff --git a/src/Avalonia.MicroCom/MicroComRuntime.cs b/src/Avalonia.MicroCom/MicroComRuntime.cs index d43568631a..9d2c23f40a 100644 --- a/src/Avalonia.MicroCom/MicroComRuntime.cs +++ b/src/Avalonia.MicroCom/MicroComRuntime.cs @@ -41,6 +41,8 @@ namespace Avalonia.MicroCom public static void* GetNativePointer(T obj, bool owned = false) where T : IUnknown { + if (obj == null) + return null; if (obj is MicroComProxyBase proxy) return (void*)proxy.NativePointer; if (obj is IMicroComShadowContainer container) @@ -55,6 +57,7 @@ namespace Avalonia.MicroCom res); if (owned) container.Shadow.AddRef((Ccw*)ptr); + return ptr; } throw new ArgumentException("Unable to get a native pointer for " + obj); } diff --git a/src/Avalonia.MicroCom/MicroComVtblBase.cs b/src/Avalonia.MicroCom/MicroComVtblBase.cs index 4cd419cdaf..e06e2d4934 100644 --- a/src/Avalonia.MicroCom/MicroComVtblBase.cs +++ b/src/Avalonia.MicroCom/MicroComVtblBase.cs @@ -18,6 +18,7 @@ namespace Avalonia.MicroCom { AddMethod((QueryInterfaceDelegate)QueryInterface); AddMethod((AddRefDelegate)AddRef); + AddMethod((AddRefDelegate)Release); } protected void AddMethod(Delegate d) diff --git a/src/Avalonia.Native/Avalonia.Native.csproj b/src/Avalonia.Native/Avalonia.Native.csproj index ecd245966e..f0c747504b 100644 --- a/src/Avalonia.Native/Avalonia.Native.csproj +++ b/src/Avalonia.Native/Avalonia.Native.csproj @@ -37,7 +37,7 @@ @@ -47,8 +47,12 @@ + + + + <_AvaloniaPatchComInterop>true - \ No newline at end of file + diff --git a/src/tools/MicroComGenerator/CSharpGen.InterfaceGen.cs b/src/tools/MicroComGenerator/CSharpGen.InterfaceGen.cs index 10c44bea21..91ece81bd0 100644 --- a/src/tools/MicroComGenerator/CSharpGen.InterfaceGen.cs +++ b/src/tools/MicroComGenerator/CSharpGen.InterfaceGen.cs @@ -135,7 +135,7 @@ namespace MicroComGenerator public override void PreMarshal(List body) { body.Add(ParseStatement($"var {BName} = new byte[System.Text.Encoding.UTF8.GetByteCount({Name})+1];")); - body.Add(ParseStatement($"System.Text.Encoding.UTF8.GetBytes({Name}, 0, {Name.Length}, {BName}, 0);")); + body.Add(ParseStatement($"System.Text.Encoding.UTF8.GetBytes({Name}, 0, {Name}.Length, {BName}, 0);")); } public override StatementSyntax CreateFixed(StatementSyntax inner) @@ -238,8 +238,11 @@ namespace MicroComGenerator .AddArgumentListArguments(Argument(ParseExpression("PPV"))) .AddArgumentListArguments(args .Select((a, i) => Argument(a.Value(isHresultLastArgumentReturn && i == args.Count - 1))).ToArray()) - .AddArgumentListArguments(Argument(ParseExpression("PPV[base.VTableSize + " + num + "]"))); + .AddArgumentListArguments(Argument(ParseExpression("(*PPV)[base.VTableSize + " + num + "]"))); + if (!isVoidReturn) + callExpr = CastExpression(ParseTypeName(returnArg.NativeType), callExpr); + // Save call result if needed if (!isVoidReturn) callExpr = AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, ParseExpression("__result"), @@ -369,6 +372,10 @@ namespace MicroComGenerator public ExpressionSyntax GetCaller(string returnType, List args) { + string ConvertType(string t) => t.EndsWith("*") ? "void*" : t; + returnType = ConvertType(returnType); + args = args.Select(ConvertType).ToList(); + var name = "CalliStdCall" + returnType.Replace("*", "_ptr"); var signature = returnType + "::" + name + "::" + string.Join("::", args); if (_existing.Add(signature)) @@ -427,7 +434,7 @@ namespace MicroComGenerator .AddModifiers(Token(SyntaxKind.StaticKeyword), Token(SyntaxKind.InternalKeyword)) .WithExpressionBody(ArrowExpressionClause( ParseExpression("Avalonia.MicroCom.MicroComRuntime.RegisterVTable(typeof(" + - proxyClassName + "), new " + vtbl.Identifier.Text + "().CreateVTable())"))) + iface.Name + "), new " + vtbl.Identifier.Text + "().CreateVTable())"))) .WithSemicolonToken(Semicolon()));