From 83d1893cfd508a13d598a4484f9258b78babbbd9 Mon Sep 17 00:00:00 2001 From: Eric Tse Date: Thu, 25 Apr 2019 15:44:57 -0400 Subject: [PATCH 1/4] WIP - Use the non-encoded type string for upcasting a shared_ptr of a derived type to a shared_ptr of the base type --- Source/Modules/java.cxx | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/Source/Modules/java.cxx b/Source/Modules/java.cxx index cb41781dd..0ad6cf6c0 100644 --- a/Source/Modules/java.cxx +++ b/Source/Modules/java.cxx @@ -1893,18 +1893,32 @@ public: * ----------------------------------------------------------------------------- */ void upcastsCode(SwigType *smart, String *upcast_method_name, String *c_classname, String *c_baseclass) { + Swig_warning(0, NULL, NULL, "******************************************\n"); + Swig_warning(0, NULL, NULL, "Smart: %s, Class name: '%s', baseclass: '%s' \n", smart, c_classname, c_baseclass); String *jniname = makeValidJniName(upcast_method_name); String *wname = Swig_name_wrapper(jniname); Printf(imclass_cppcasts_code, " public final static native long %s(long jarg1);\n", upcast_method_name); if (smart) { - SwigType *bsmart = Copy(smart); + String *smartnamestr = SwigType_namestr(smart); + String *bsmartnamestr = SwigType_namestr(smart); + SwigType *rclassname = SwigType_typedef_resolve_all(c_classname); + Swig_warning(0, NULL, NULL, "SwigType_typedef_resolve_all - c_classname(%s): '%s'\n", c_classname, rclassname); + SwigType *rbaseclass = SwigType_typedef_resolve_all(c_baseclass); - Replaceall(bsmart, rclassname, rbaseclass); + Swig_warning(0, NULL, NULL, "SwigType_typedef_resolve_all - c_baseclass(%s): '%s'\n", c_baseclass, rbaseclass); + + Swig_warning(0, NULL, NULL, "Replaceall - PRE(%s, %s, %s)\n", bsmartnamestr, rclassname, rbaseclass); + Replaceall(bsmartnamestr, rclassname, rbaseclass); + Swig_warning(0, NULL, NULL, "Replaceall - POST(%s, %s, %s)\n", bsmartnamestr, rclassname, rbaseclass); + Delete(rclassname); Delete(rbaseclass); - String *smartnamestr = SwigType_namestr(smart); - String *bsmartnamestr = SwigType_namestr(bsmart); + //String *smartnamestr = SwigType_namestr(smart); + //String *bsmartnamestr = SwigType_namestr(bsmart); + Swig_warning(0, NULL, NULL, "bsmartnamestr: '%s', smartnamestr: '%s' \n", bsmartnamestr, smartnamestr); + + Printv(upcasts_code, "SWIGEXPORT jlong JNICALL ", wname, "(JNIEnv *jenv, jclass jcls, jlong jarg1) {\n", " jlong baseptr = 0;\n" @@ -1917,7 +1931,6 @@ public: "}\n", "\n", NIL); Delete(bsmartnamestr); Delete(smartnamestr); - Delete(bsmart); } else { Printv(upcasts_code, "SWIGEXPORT jlong JNICALL ", wname, "(JNIEnv *jenv, jclass jcls, jlong jarg1) {\n", @@ -1928,6 +1941,8 @@ public: " return baseptr;\n" "}\n", "\n", NIL); } + Swig_warning(0, NULL, NULL, "******************************************\n"); + Delete(wname); Delete(jniname); } From 5f42bed04eacc61f45c113131afe280ad0cdfa8a Mon Sep 17 00:00:00 2001 From: etse Date: Wed, 1 May 2019 17:05:44 -0400 Subject: [PATCH 2/4] Adding test case demonstrating issue where SWIG does not generate a correctly typed, upcasted shared_ptr for a template instantiation deriving from a base class --- .../cpp11_shared_ptr_template_upcast.i | 88 +++++++++++++++++++ Examples/test-suite/java/Makefile.in | 1 + ...pp11_shared_ptr_template_upcast_runme.java | 25 ++++++ 3 files changed, 114 insertions(+) create mode 100644 Examples/test-suite/cpp11_shared_ptr_template_upcast.i create mode 100644 Examples/test-suite/java/cpp11_shared_ptr_template_upcast_runme.java diff --git a/Examples/test-suite/cpp11_shared_ptr_template_upcast.i b/Examples/test-suite/cpp11_shared_ptr_template_upcast.i new file mode 100644 index 000000000..69ffec5bf --- /dev/null +++ b/Examples/test-suite/cpp11_shared_ptr_template_upcast.i @@ -0,0 +1,88 @@ +%module cpp11_shared_ptr_template_upcast + +%{ +#include +#include +%} + +%include +%include + +%{ +class Base { +public: + Base() : value(0) {} + Base(int v) : value(v) {} + virtual ~Base() {} + + virtual int GetResult() = 0; + + int value; +}; + +class Derived : public Base { +public: + Derived() : Base() {} + Derived(int v) : Base(v) {} + virtual ~Derived() {} + + int GetResult() { return value*2; } +}; + +template class Printable : virtual public T { +public: + Printable(int param) : T(param) {} + ~Printable() {} + + std::string GetFormatted() { return std::string("The formatted result is: ").append(std::to_string(this->GetResult())); } +}; + +std::shared_ptr > MakePrintableDerived(int param) { + return std::make_shared >(param); +} + +%} + +%shared_ptr(Base); +%shared_ptr(Derived); +%shared_ptr(Printable) + +class Base { +public: + Base(); + Base(int v); + virtual ~Base(); + + virtual int GetResult() = 0; + + int value; +}; + +class Derived : public Base { +public: + Derived(); + Derived(int v); + virtual ~Derived(); + + int GetResult(); +}; + +/* + Contrived for this case (but valid for others, such as if Printable was to be a interface/abstract base class). + Virtual inheritance exposes whether SWIGSmartPtrUpcast generated a correctly typed shared pointer of the upcasted class type - if the pointer type is incorrect, this will result in + a segmentation fault (on Windows, this could manifest as undefined behavior) when trying to access any member inherited from T through a shared_ptr >. +*/ +template class Printable : virtual public T { +public: + Printable(int param); + ~Printable(); + + std::string GetFormatted(); +}; + +std::shared_ptr > MakePrintableDerived(int param); + + +%template(PrintableDerived) Printable; + + diff --git a/Examples/test-suite/java/Makefile.in b/Examples/test-suite/java/Makefile.in index 2e788fa07..3954b939a 100644 --- a/Examples/test-suite/java/Makefile.in +++ b/Examples/test-suite/java/Makefile.in @@ -52,6 +52,7 @@ CPP11_TEST_CASES = \ cpp11_shared_ptr_const \ cpp11_shared_ptr_nullptr_in_containers \ cpp11_shared_ptr_overload \ + cpp11_shared_ptr_template_upcast \ cpp11_shared_ptr_upcast \ cpp11_std_unordered_map \ cpp11_std_unordered_set \ diff --git a/Examples/test-suite/java/cpp11_shared_ptr_template_upcast_runme.java b/Examples/test-suite/java/cpp11_shared_ptr_template_upcast_runme.java new file mode 100644 index 000000000..b367fef5e --- /dev/null +++ b/Examples/test-suite/java/cpp11_shared_ptr_template_upcast_runme.java @@ -0,0 +1,25 @@ + +// This is the cpp11_shared_ptr_template_upcast runtime testcase. It checks that SWIG generates the appropriate, upcasted shared_ptr type for a template instantiation deriving from a base class. +// In this case, the expected behavior is that given a cptr (underlying type shared_ptr >), PrintableDerived_SWIGSmartPtrUpcast returns a cptr +// (underlying type std::shared_ptr< Derived >). + +import cpp11_shared_ptr_template_upcast.*; + +public class cpp11_shared_ptr_template_upcast_runme { + + static { + try { + System.loadLibrary("cpp11_shared_ptr_template_upcast"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); + System.exit(1); + } + } + + public static void main(String argv[]) { + PrintableDerived pd = cpp11_shared_ptr_template_upcast.MakePrintableDerived(20); + pd.GetResult(); + pd.GetFormatted(); + } +} + From ab7f526805b86726a3c23c853e0ab19458f2c7d9 Mon Sep 17 00:00:00 2001 From: etse Date: Thu, 2 May 2019 13:29:22 -0400 Subject: [PATCH 3/4] Applying shared_ptr template upcast fix to CSharp, adding CSharp test, and cleanup --- Examples/test-suite/csharp/Makefile.in | 1 + .../cpp11_shared_ptr_template_upcast_runme.cs | 15 +++++++++++++++ .../cpp11_shared_ptr_template_upcast_runme.java | 7 +++---- Source/Modules/csharp.cxx | 11 ++++++----- Source/Modules/java.cxx | 12 ------------ 5 files changed, 25 insertions(+), 21 deletions(-) create mode 100644 Examples/test-suite/csharp/cpp11_shared_ptr_template_upcast_runme.cs diff --git a/Examples/test-suite/csharp/Makefile.in b/Examples/test-suite/csharp/Makefile.in index c9e48f804..dd87fb6d7 100644 --- a/Examples/test-suite/csharp/Makefile.in +++ b/Examples/test-suite/csharp/Makefile.in @@ -33,6 +33,7 @@ CPP11_TEST_CASES = \ cpp11_shared_ptr_const \ cpp11_shared_ptr_nullptr_in_containers \ cpp11_shared_ptr_overload \ + cpp11_shared_ptr_template_upcast \ cpp11_shared_ptr_upcast \ cpp11_strongly_typed_enumerations_simple \ diff --git a/Examples/test-suite/csharp/cpp11_shared_ptr_template_upcast_runme.cs b/Examples/test-suite/csharp/cpp11_shared_ptr_template_upcast_runme.cs new file mode 100644 index 000000000..e76d2bada --- /dev/null +++ b/Examples/test-suite/csharp/cpp11_shared_ptr_template_upcast_runme.cs @@ -0,0 +1,15 @@ +// This is the cpp11_shared_ptr_template_upcast runtime testcase. It checks that SWIG generates the appropriate upcasted shared_ptr type for a template instantiation deriving from a base class. +// For this case, the expected behavior is: given a cptr with underlying type shared_ptr >, PrintableDerived_SWIGSmartPtrUpcast returns a cptr with +// underlying type std::shared_ptr< Derived >, where Printable inherits from Derived. +using System; +using cpp11_shared_ptr_template_upcastNamespace; + +public class cpp11_shared_ptr_template_upcast_runme +{ + static void Main() + { + PrintableDerived pd = cpp11_shared_ptr_template_upcast.MakePrintableDerived(20); + pd.GetResult(); + pd.GetFormatted(); + } +} diff --git a/Examples/test-suite/java/cpp11_shared_ptr_template_upcast_runme.java b/Examples/test-suite/java/cpp11_shared_ptr_template_upcast_runme.java index b367fef5e..2826f580d 100644 --- a/Examples/test-suite/java/cpp11_shared_ptr_template_upcast_runme.java +++ b/Examples/test-suite/java/cpp11_shared_ptr_template_upcast_runme.java @@ -1,7 +1,6 @@ - -// This is the cpp11_shared_ptr_template_upcast runtime testcase. It checks that SWIG generates the appropriate, upcasted shared_ptr type for a template instantiation deriving from a base class. -// In this case, the expected behavior is that given a cptr (underlying type shared_ptr >), PrintableDerived_SWIGSmartPtrUpcast returns a cptr -// (underlying type std::shared_ptr< Derived >). +// This is the cpp11_shared_ptr_template_upcast runtime testcase. It checks that SWIG generates the appropriate upcasted shared_ptr type for a template instantiation deriving from a base class. +// For this case, the expected behavior is: given a cptr with underlying type shared_ptr >, PrintableDerived_SWIGSmartPtrUpcast returns a cptr with +// underlying type std::shared_ptr< Derived >, where Printable inherits from Derived. import cpp11_shared_ptr_template_upcast.*; diff --git a/Source/Modules/csharp.cxx b/Source/Modules/csharp.cxx index ff73c3075..8522fb87c 100644 --- a/Source/Modules/csharp.cxx +++ b/Source/Modules/csharp.cxx @@ -1758,21 +1758,22 @@ public: Replaceall(imclass_cppcasts_code, "$csclassname", proxy_class_name); if (smart) { - SwigType *bsmart = Copy(smart); + String *smartnamestr = SwigType_namestr(smart); + String *bsmartnamestr = SwigType_namestr(smart); + SwigType *rclassname = SwigType_typedef_resolve_all(c_classname); SwigType *rbaseclass = SwigType_typedef_resolve_all(c_baseclass); - Replaceall(bsmart, rclassname, rbaseclass); + Replaceall(bsmartnamestr, rclassname, rbaseclass); + Delete(rclassname); Delete(rbaseclass); - String *smartnamestr = SwigType_namestr(smart); - String *bsmartnamestr = SwigType_namestr(bsmart); + Printv(upcasts_code, "SWIGEXPORT ", bsmartnamestr, " * SWIGSTDCALL ", wname, "(", smartnamestr, " *jarg1) {\n", " return jarg1 ? new ", bsmartnamestr, "(*jarg1) : 0;\n" "}\n", "\n", NIL); Delete(bsmartnamestr); Delete(smartnamestr); - Delete(bsmart); } else { Printv(upcasts_code, "SWIGEXPORT ", c_baseclass, " * SWIGSTDCALL ", wname, "(", c_classname, " *jarg1) {\n", diff --git a/Source/Modules/java.cxx b/Source/Modules/java.cxx index 0ad6cf6c0..da27214e3 100644 --- a/Source/Modules/java.cxx +++ b/Source/Modules/java.cxx @@ -1893,8 +1893,6 @@ public: * ----------------------------------------------------------------------------- */ void upcastsCode(SwigType *smart, String *upcast_method_name, String *c_classname, String *c_baseclass) { - Swig_warning(0, NULL, NULL, "******************************************\n"); - Swig_warning(0, NULL, NULL, "Smart: %s, Class name: '%s', baseclass: '%s' \n", smart, c_classname, c_baseclass); String *jniname = makeValidJniName(upcast_method_name); String *wname = Swig_name_wrapper(jniname); Printf(imclass_cppcasts_code, " public final static native long %s(long jarg1);\n", upcast_method_name); @@ -1903,21 +1901,12 @@ public: String *bsmartnamestr = SwigType_namestr(smart); SwigType *rclassname = SwigType_typedef_resolve_all(c_classname); - Swig_warning(0, NULL, NULL, "SwigType_typedef_resolve_all - c_classname(%s): '%s'\n", c_classname, rclassname); - SwigType *rbaseclass = SwigType_typedef_resolve_all(c_baseclass); - Swig_warning(0, NULL, NULL, "SwigType_typedef_resolve_all - c_baseclass(%s): '%s'\n", c_baseclass, rbaseclass); - Swig_warning(0, NULL, NULL, "Replaceall - PRE(%s, %s, %s)\n", bsmartnamestr, rclassname, rbaseclass); Replaceall(bsmartnamestr, rclassname, rbaseclass); - Swig_warning(0, NULL, NULL, "Replaceall - POST(%s, %s, %s)\n", bsmartnamestr, rclassname, rbaseclass); Delete(rclassname); Delete(rbaseclass); - //String *smartnamestr = SwigType_namestr(smart); - //String *bsmartnamestr = SwigType_namestr(bsmart); - Swig_warning(0, NULL, NULL, "bsmartnamestr: '%s', smartnamestr: '%s' \n", bsmartnamestr, smartnamestr); - Printv(upcasts_code, "SWIGEXPORT jlong JNICALL ", wname, "(JNIEnv *jenv, jclass jcls, jlong jarg1) {\n", @@ -1941,7 +1930,6 @@ public: " return baseptr;\n" "}\n", "\n", NIL); } - Swig_warning(0, NULL, NULL, "******************************************\n"); Delete(wname); Delete(jniname); From 997c7a1570f35ecee7fcbe047699ea2cb0ce4efb Mon Sep 17 00:00:00 2001 From: etse Date: Thu, 2 May 2019 18:22:33 -0400 Subject: [PATCH 4/4] comments --- Examples/test-suite/cpp11_shared_ptr_template_upcast.i | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Examples/test-suite/cpp11_shared_ptr_template_upcast.i b/Examples/test-suite/cpp11_shared_ptr_template_upcast.i index 69ffec5bf..38968bb60 100644 --- a/Examples/test-suite/cpp11_shared_ptr_template_upcast.i +++ b/Examples/test-suite/cpp11_shared_ptr_template_upcast.i @@ -68,9 +68,9 @@ public: }; /* - Contrived for this case (but valid for others, such as if Printable was to be a interface/abstract base class). - Virtual inheritance exposes whether SWIGSmartPtrUpcast generated a correctly typed shared pointer of the upcasted class type - if the pointer type is incorrect, this will result in - a segmentation fault (on Windows, this could manifest as undefined behavior) when trying to access any member inherited from T through a shared_ptr >. + Virtual inheritance is contrived for this case, but exposes whether SWIGSmartPtrUpcast generated a correctly typed shared pointer of the upcasted class type - + if the pointer type is incorrect, this will result in a segmentation fault (on Windows, this could manifest as undefined behavior) when trying to access members + inherited from T through a shared_ptr >. */ template class Printable : virtual public T { public: