Browse Source

Forbid the disposal of unowned objects and simplified the generated code.

Signed-off-by: Dimitar Dobrev <dpldobrev@yahoo.com>
pull/553/head
Dimitar Dobrev 10 years ago
parent
commit
5dca339ff2
  1. 61
      src/Generator/Generators/CSharp/CSharpTextTemplate.cs
  2. 9
      tests/CSharp/CSharp.Tests.cs

61
src/Generator/Generators/CSharp/CSharpTextTemplate.cs

@ -1475,7 +1475,7 @@ namespace CppSharp.Generators.CSharp
{ {
if (method.IsDestructor) if (method.IsDestructor)
{ {
WriteLine("{0}.DestroyNativeInstance();", Helpers.TargetIdentifier); WriteLine("{0}.Dispose(false);", Helpers.TargetIdentifier);
return; return;
} }
@ -1784,11 +1784,14 @@ namespace CppSharp.Generators.CSharp
if (@class.IsRefType) if (@class.IsRefType)
{ {
GenerateClassFinalizer(@class); GenerateClassFinalizer(@class);
GenerateDisposeMethods(@class);
// Only root bases need a Dispose
if (ShouldGenerateClassNativeField(@class))
GenerateDisposeMethods(@class);
} }
} }
private void GenerateClassFinalizer(Class @class) private void GenerateClassFinalizer(INamedDecl @class)
{ {
if (!Options.GenerateFinalizers) if (!Options.GenerateFinalizers)
return; return;
@ -1836,21 +1839,9 @@ namespace CppSharp.Generators.CSharp
WriteLine("void Dispose(bool disposing)"); WriteLine("void Dispose(bool disposing)");
WriteStartBraceIndent(); WriteStartBraceIndent();
const string destroyNativeInstance = "DestroyNativeInstance"; WriteLine("if (!{0} && disposing)", Helpers.OwnsNativeInstanceIdentifier);
WriteLine("{0}(false);", destroyNativeInstance); WriteLineIndent("throw new global::System.InvalidOperationException" +
if (hasBaseClass) "(\"Managed instances owned by native code cannot be disposed of.\");");
WriteLine("base.Dispose(disposing);");
WriteCloseBraceIndent();
NewLine();
WriteLine("public {0} void {1}()", hasBaseClass ? "override" : "virtual", destroyNativeInstance);
WriteStartBraceIndent();
WriteLine("{0}(true);", destroyNativeInstance);
WriteCloseBraceIndent();
NewLine();
WriteLine("private void {0}(bool force)", destroyNativeInstance);
WriteStartBraceIndent();
if (@class.IsRefType) if (@class.IsRefType)
{ {
@ -1878,34 +1869,22 @@ namespace CppSharp.Generators.CSharp
} }
var dtor = @class.Destructors.FirstOrDefault(); var dtor = @class.Destructors.FirstOrDefault();
if (ShouldGenerateClassNativeField(@class)) if (dtor != null && dtor.Access != AccessSpecifier.Private &&
@class.HasNonTrivialDestructor && !dtor.IsPure)
{ {
if (dtor != null && dtor.Access != AccessSpecifier.Private && NativeLibrary library;
@class.HasNonTrivialDestructor && !dtor.IsPure) if (!Options.CheckSymbols ||
Driver.Symbols.FindLibraryBySymbol(dtor.Mangled, out library))
{ {
NativeLibrary library; if (dtor.IsVirtual)
if (!Options.CheckSymbols || GenerateVirtualFunctionCall(dtor, @class);
Driver.Symbols.FindLibraryBySymbol(dtor.Mangled, out library)) else
{ GenerateInternalFunctionCall(dtor);
WriteLine("if ({0} || force)", Helpers.OwnsNativeInstanceIdentifier);
if (dtor.IsVirtual)
{
WriteStartBraceIndent();
GenerateVirtualFunctionCall(dtor, @class);
WriteCloseBraceIndent();
}
else
{
GenerateInternalFunctionCall(dtor);
}
}
} }
WriteLine("if ({0})", Helpers.OwnsNativeInstanceIdentifier);
WriteLineIndent("Marshal.FreeHGlobal({0});", Helpers.InstanceIdentifier);
} }
WriteLine("Marshal.FreeHGlobal({0});", Helpers.InstanceIdentifier);
WriteCloseBraceIndent(); WriteCloseBraceIndent();
PopBlock(NewLineKind.BeforeNextBlock); PopBlock(NewLineKind.BeforeNextBlock);
} }

9
tests/CSharp/CSharp.Tests.cs

@ -311,11 +311,10 @@ public class CSharpTests : GeneratorTestFixture
using (var testNativeToManagedMap = new TestNativeToManagedMap()) using (var testNativeToManagedMap = new TestNativeToManagedMap())
{ {
var hasVirtualDtor2 = testNativeToManagedMap.HasVirtualDtor2; var hasVirtualDtor2 = testNativeToManagedMap.HasVirtualDtor2;
hasVirtualDtor2.Dispose(); Assert.Catch<InvalidOperationException>(hasVirtualDtor2.Dispose);
using (var hasVirtualDtor1 = hasVirtualDtor2.HasVirtualDtor1) var hasVirtualDtor1 = hasVirtualDtor2.HasVirtualDtor1;
{ Assert.AreEqual(5, hasVirtualDtor1.TestField);
Assert.AreEqual(5, hasVirtualDtor1.TestField); Assert.Catch<InvalidOperationException>(hasVirtualDtor1.Dispose);
}
} }
} }

Loading…
Cancel
Save