diff --git a/CHANGES.current b/CHANGES.current index f15c99e90..0acfddc7d 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,16 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.0.0 (in progress) =========================== +2018-05-11: wsfulton + [C#, D, Java] Add support so that the %csmethodmodifiers, %dmethodmodifiers, + %javamethodmodifiers can modify the method modifiers for the destructor wrappers + in the proxy class: dispose, Dispose, delete. With this feature, it is now possible + to make a C# proxy class sealed, eg when wrapping a class X, the virtual method modifiers + can be removed using: + + %typemap(csclassmodifiers) X "public sealed class" + %csmethodmodifiers X::~X "public /*virtual*/"; + 2018-04-18: olly [Python] Suppress new pycodestyle warning: E252 missing whitespace around parameter equals diff --git a/Doc/Manual/CSharp.html b/Doc/Manual/CSharp.html index 13b6e4997..e96940626 100644 --- a/Doc/Manual/CSharp.html +++ b/Doc/Manual/CSharp.html @@ -44,7 +44,8 @@
@@ -2615,7 +2616,97 @@ demonstrating that the class contains methods calling both unmanaged code - The following example is an alternative approach to adding managed code to the generated proxy class.
-+The technique in the previous section can be used to make the proxy class a sealed class. +Consider a C++ class NotABaseClass that you don't want to be derived from in C#: +
+ +
+struct NotABaseClass {
+ NotABaseClass();
+ ~NotABaseClass();
+};
+
++The default C# proxy class method generated with Dispose method is: +
+ +
+public class NotABaseClass : global::System.IDisposable {
+ ...
+ public virtual void Dispose() {
+ ...
+ }
+}
+
++The csclassmodifiers typemap can be used to modify the class modifiers and +the csmethodmodifiers feature can be used on the destructor to modify the proxy's Dispose method: +
+ ++%typemap(csclassmodifiers) NotABaseClass "public sealed class" +%csmethodmodifiers NotABaseClass::~NotABaseClass "public /*virtual*/"; ++
+The relevant generated code is thus: +
+ +
+public sealed class NotABaseClass : global::System.IDisposable {
+ ...
+ public /*virtual*/ void Dispose() {
+ ...
+ }
+}
+
++Any attempt to derive from the NotABaseClass in C# will result in a C# compiler error, for example: +
+ +
+public class Derived : NotABaseClass {
+};
+
++runme.cs(6,14): error CS0509: `Derived': cannot derive from sealed type `NotABaseClass' ++
+Finally, if you get a warning about use of 'protected' in the generated base class: +
+ ++NotABaseClass.cs(14,18): warning CS0628: `NotABaseClass.swigCMemOwn': new protected member declared in sealed class ++
+Either suppress the warning or modify the generated code by copying and tweaking the default +'csbody' typemap code in csharp.swg by modifying swigCMemOwn to not be protected. +
+ +@@ -2654,7 +2745,7 @@ public class ExtendMe : global::System.IDisposable { -
diff --git a/Doc/Manual/Contents.html b/Doc/Manual/Contents.html index 5cc796c8d..f77823d20 100644 --- a/Doc/Manual/Contents.html +++ b/Doc/Manual/Contents.html @@ -787,7 +787,8 @@
%typemap(javadestruct_derived, methodname="delete", methodmodifiers="public synchronized")
@@ -6571,6 +6573,8 @@ same as "javadestruct" but only used for derived proxy classes%typemap(javaimports)
diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index d75d3242e..72c49648b 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -170,6 +170,7 @@ CPP_TEST_CASES += \ defvalue_constructor \ derived_byvalue \ derived_nested \ + destructor_methodmodifiers \ destructor_reprotected \ director_abstract \ director_alternating \ diff --git a/Examples/test-suite/destructor_methodmodifiers.i b/Examples/test-suite/destructor_methodmodifiers.i new file mode 100644 index 000000000..93db7f2cc --- /dev/null +++ b/Examples/test-suite/destructor_methodmodifiers.i @@ -0,0 +1,61 @@ +%module destructor_methodmodifiers + +// This test changes the proxy classes so that they cannot be inherited from in the target language +// Previously the %csmethodmodifiers, %dmethodmodifiers, %javamethodmodifiers on destructors were ignored +// Now they can control the dispose/Dispose/delete method modifiers + +#if defined(SWIGCSHARP) + +// remove all use of protected and virtual keywords +%typemap(csclassmodifiers) NotForDeriving1, NotForDeriving2 "public sealed class" +%csmethodmodifiers NotForDeriving1::~NotForDeriving1 "public /*not virtual nor override*/"; +%csmethodmodifiers NotForDeriving2::~NotForDeriving2 "public /*not virtual nor override*/"; + +// remove protected keyword to remove compiler warning +%typemap(csbody) NotForDeriving1, NotForDeriving2 %{ + private global::System.Runtime.InteropServices.HandleRef swigCPtr; + private /*protected*/ bool swigCMemOwn; + + internal $csclassname(global::System.IntPtr cPtr, bool cMemoryOwn) { + swigCMemOwn = cMemoryOwn; + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(this, cPtr); + } + + internal static global::System.Runtime.InteropServices.HandleRef getCPtr($csclassname obj) { + return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr; + } +%} + +#elif defined(SWIGD) + +%typemap(dclassmodifiers) NotForDeriving1, NotForDeriving2 "final class" +%dmethodmodifiers NotForDeriving1::~NotForDeriving1 "public final"; +%dmethodmodifiers NotForDeriving2::~NotForDeriving2 "public final"; + +#elif defined(SWIGJAVA) + +%typemap(javaclassmodifiers) NotForDeriving1, NotForDeriving2 "public final class" +%javamethodmodifiers NotForDeriving1::~NotForDeriving1 "public synchronized final"; +%javamethodmodifiers NotForDeriving2::~NotForDeriving2 "public synchronized final"; + +#endif + +%inline %{ +//#include