diff --git a/src/Generator/Generators/CSharp/CSharpMarshal.cs b/src/Generator/Generators/CSharp/CSharpMarshal.cs index cbca5f0c..e06d7eb3 100644 --- a/src/Generator/Generators/CSharp/CSharpMarshal.cs +++ b/src/Generator/Generators/CSharp/CSharpMarshal.cs @@ -282,7 +282,48 @@ namespace CppSharp.Generators.CSharp if (returnType.IsAddress()) Context.Return.Write(HandleReturnedPointer(@class, qualifiedClass)); else - Context.Return.Write($"{qualifiedClass}.{Helpers.CreateInstanceIdentifier}({Context.ReturnVarName})"); + { + if (Context.MarshalKind == MarshalKind.NativeField || + Context.MarshalKind == MarshalKind.Variable || + !originalClass.HasNonTrivialDestructor) + { + Context.Return.Write($"{qualifiedClass}.{Helpers.CreateInstanceIdentifier}({Context.ReturnVarName})"); + } + else + { + Context.Before.WriteLine($@"var __{Context.ReturnVarName} = { + qualifiedClass}.{Helpers.CreateInstanceIdentifier}({Context.ReturnVarName});"); + Method dtor = originalClass.Destructors.First(); + if (dtor.IsVirtual) + { + var i = VTables.GetVTableIndex(dtor); + int vtableIndex = 0; + if (Context.Context.ParserOptions.IsMicrosoftAbi) + vtableIndex = @class.Layout.VFTables.IndexOf(@class.Layout.VFTables.First( + v => v.Layout.Components.Any(c => c.Method == dtor))); + Context.Before.WriteLine($@"var __vtables = new IntPtr[] {{ { + string.Join(", ", originalClass.Layout.VTablePointers.Select( + x => $" * (IntPtr*) ({ Helpers.InstanceIdentifier} + {x.Offset})"))} }};"); + Context.Before.WriteLine($"var __slot = *(IntPtr*) (__vtables[{vtableIndex}] + {i} * sizeof(IntPtr));"); + Context.Before.Write($"Marshal.GetDelegateForFunctionPointer<{dtor.FunctionType}>(__slot)({Helpers.InstanceIdentifier}"); + if (dtor.GatherInternalParams(Context.Context.ParserOptions.IsItaniumLikeAbi).Count > 1) + { + Context.Before.WriteLine(", 0"); + } + Context.Before.WriteLine(");"); + } + else + { + string suffix = string.Empty; + var specialization = @class as ClassTemplateSpecialization; + if (specialization != null) + suffix = Helpers.GetSuffixFor(specialization); + Context.Before.WriteLine($@"{typePrinter.PrintNative(originalClass)}.dtor{ + suffix}(new {typePrinter.IntPtrType}(&{Context.ReturnVarName}));"); + } + Context.Return.Write($"__{Context.ReturnVarName}"); + } + } return true; } diff --git a/src/Generator/Generators/CSharp/CSharpSources.cs b/src/Generator/Generators/CSharp/CSharpSources.cs index d6361a34..0244c89b 100644 --- a/src/Generator/Generators/CSharp/CSharpSources.cs +++ b/src/Generator/Generators/CSharp/CSharpSources.cs @@ -1334,8 +1334,15 @@ namespace CppSharp.Generators.CSharp AddBlock(new Block(BlockKind.Unreachable)); return; } - GenerateFunctionInProperty(@class, actualProperty.GetMethod, actualProperty, - property.QualifiedType); + QualifiedType type = default; + if (actualProperty != property || + // indexers + (property.QualifiedType.Type.IsPrimitiveType() && + actualProperty.GetMethod.ReturnType.Type.IsPointerToPrimitiveType())) + { + type = property.QualifiedType; + } + GenerateFunctionInProperty(@class, actualProperty.GetMethod, actualProperty, type); } private static Property GetActualProperty(Property property, Class c) @@ -2180,10 +2187,8 @@ namespace CppSharp.Generators.CSharp // ensure any virtual dtor in the chain is called var dtor = @class.Destructors.FirstOrDefault(d => d.Access != AccessSpecifier.Private); - var baseDtor = @class.BaseClass == null ? null : - @class.BaseClass.Destructors.FirstOrDefault(d => !d.IsVirtual); if (ShouldGenerateClassNativeField(@class) || - ((dtor != null && (dtor.IsVirtual || @class.HasNonTrivialDestructor)) && baseDtor != null) || + (dtor != null && (dtor.IsVirtual || @class.HasNonTrivialDestructor)) || // virtual destructors in abstract classes may lack a pointer in the v-table // so they have to be called by symbol; thus we need an explicit Dispose override @class.IsAbstract) @@ -3464,11 +3469,6 @@ internal static{(@new ? " new" : string.Empty)} {printedClass} __GetInstance({Ty if (function.IsPure) return; - if (function.OriginalName == "system_do_it") - { - System.Diagnostics.Debugger.Break(); - } - PushBlock(BlockKind.InternalsClassMethod); var callConv = function.CallingConvention.ToInteropCallConv(); diff --git a/tests/CSharp/CSharpTemplates.h b/tests/CSharp/CSharpTemplates.h index 9bdce147..213f6ce2 100644 --- a/tests/CSharp/CSharpTemplates.h +++ b/tests/CSharp/CSharpTemplates.h @@ -794,6 +794,7 @@ template class DLL_API Base; template class DLL_API DependentValueFields; template class DLL_API DependentValueFields; template class DLL_API DependentValueFields; +template class DLL_API DependentValueFields; template class DLL_API DependentPointerFields; template class DLL_API VirtualTemplate; template class DLL_API VirtualTemplate; diff --git a/tests/Common/Common.Tests.cs b/tests/Common/Common.Tests.cs index 0b42f982..08a464fe 100644 --- a/tests/Common/Common.Tests.cs +++ b/tests/Common/Common.Tests.cs @@ -1127,6 +1127,15 @@ This is a very long string. This is a very long string. This is a very long stri } } + [Test] + public void TestReturnByValueWithReturnParam() + { + using (var returnByValueWithReturnParam = ReturnByValueWithReturnParamFactory.Generate()) + { + Assert.That(returnByValueWithReturnParam.UseCount, Is.EqualTo(1)); + } + } + [Test, Ignore("This was exposed by another bug and doesn't work yet.")] public void TestFreeFunctionReturnByValue() { diff --git a/tests/Common/Common.cpp b/tests/Common/Common.cpp index 3c14d9eb..986c5236 100644 --- a/tests/Common/Common.cpp +++ b/tests/Common/Common.cpp @@ -1336,6 +1336,19 @@ HasPropertyNamedAsParent::~HasPropertyNamedAsParent() { } +ReturnByValueWithReturnParam::ReturnByValueWithReturnParam() {} + +ReturnByValueWithReturnParam::ReturnByValueWithReturnParam(const ReturnByValueWithReturnParam& other) : _ptr(other._ptr) {} + +ReturnByValueWithReturnParam::~ReturnByValueWithReturnParam() {} + +int ReturnByValueWithReturnParam::getUseCount() { return _ptr.use_count(); } + +ReturnByValueWithReturnParam ReturnByValueWithReturnParamFactory::generate() +{ + return ReturnByValueWithReturnParam(); +} + void integerOverload(int i) { } diff --git a/tests/Common/Common.h b/tests/Common/Common.h index 1b684734..a0848e26 100644 --- a/tests/Common/Common.h +++ b/tests/Common/Common.h @@ -1355,6 +1355,24 @@ public: int hasPropertyNamedAsParent; }; +class DLL_API ReturnByValueWithReturnParam +{ +public: + ReturnByValueWithReturnParam(); + ReturnByValueWithReturnParam(const ReturnByValueWithReturnParam& other); + ~ReturnByValueWithReturnParam(); + int getUseCount(); + +private: + std::shared_ptr _ptr = std::shared_ptr(new int[1]); +}; + +class DLL_API ReturnByValueWithReturnParamFactory +{ +public: + static ReturnByValueWithReturnParam generate(); +}; + template void TemplatedFunction(T type) {