From 01277d700ca44e695d584838dc42c98e035ad514 Mon Sep 17 00:00:00 2001 From: Thomas Reitmayr Date: Tue, 9 Jun 2020 21:58:47 +0200 Subject: Unwrap director classes only when returning a pointer or reference to an object This involves properly counting the number of references and pointers in the return type of a function and only generate unwrapping code if this number is 1. For template instances some post-processing code is added to fix the 'decl' and 'type' attributes of functions if changed in an unfavorable way during template expansion. This commit fixes swig#1811. --- Examples/test-suite/common.mk | 1 + Examples/test-suite/director_unwrap_result.i | 82 ++++++++++++++++ Examples/test-suite/javascript/Makefile.in | 1 + .../ruby/director_unwrap_result_runme.rb | 106 +++++++++++++++++++++ 4 files changed, 190 insertions(+) create mode 100644 Examples/test-suite/director_unwrap_result.i create mode 100644 Examples/test-suite/ruby/director_unwrap_result_runme.rb (limited to 'Examples/test-suite') diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index e77f09c86..abc1e9997 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -213,6 +213,7 @@ CPP_TEST_CASES += \ director_smartptr \ director_thread \ director_unroll \ + director_unwrap_result \ director_using \ director_void \ director_wombat \ diff --git a/Examples/test-suite/director_unwrap_result.i b/Examples/test-suite/director_unwrap_result.i new file mode 100644 index 000000000..bcb7f0fcc --- /dev/null +++ b/Examples/test-suite/director_unwrap_result.i @@ -0,0 +1,82 @@ +%module(directors="1") director_unwrap_result + +%warnfilter(SWIGWARN_TYPEMAP_DIRECTOROUT_PTR) Storage; +%warnfilter(SWIGWARN_TYPEMAP_DIRECTOROUT_PTR) StorageTmpl; + +%feature("director") Element; +%feature("director") Storage; +%feature("director") StorageTmpl; + +%inline %{ + +class Element { + Element* self; + Element** selfptr; + public: + Element() { + self = this; + selfptr = &self; + } + virtual ~Element() {} + Element **getPtrPtr() { + return &self; + } + Element ***getPtrPtrPtr() { + return &selfptr; + } +}; + +class Storage { + public: + virtual ~Storage() {} + virtual Element **getIt() = 0; + Element getElement() { + return **getIt(); + } + Element* const getElementPtr() { + return *getIt(); + } + Element& getElementRef() { + return **getIt(); + } + Element* const *getElementPtrPtr() { + return getIt(); + } + Element *&getElementPtrRef() { + return *getIt(); + } +}; + +template class StorageTmpl { + public: + virtual ~StorageTmpl() {} + virtual T &getIt() = 0; + T getVal() { + return getIt(); + } + T *getPtr() { + return &getIt(); + } + T &getRef() { + return getIt(); + } +}; + +%} + +%template(ElementStorage) StorageTmpl; +%template(ElementPtrStorage) StorageTmpl; +%template(ElementPtrPtrStorage) StorageTmpl; + +%inline %{ + +template T getParam(T t) { + return t; +} + +%} + +%template(getIntParam) getParam; +%template(getIntPtrParam) getParam; +%template(getElementPtrParam) getParam; + diff --git a/Examples/test-suite/javascript/Makefile.in b/Examples/test-suite/javascript/Makefile.in index 8127415f1..bf7f24236 100644 --- a/Examples/test-suite/javascript/Makefile.in +++ b/Examples/test-suite/javascript/Makefile.in @@ -52,6 +52,7 @@ ifeq (node,$(JSENGINE)) apply_signed_char.cpptest: GYP_CFLAGS = \"-Wno-ignored-qualifiers\" constant_pointers.cpptest: GYP_CFLAGS = \"-Wno-ignored-qualifiers\" enum_thorough.cpptest: GYP_CFLAGS = \"-Wno-ignored-qualifiers\" + director_unwrap_result.cpptest: GYP_CFLAGS = \"-Wno-ignored-qualifiers\" setup_node = \ test -d $* || mkdir $* && \ diff --git a/Examples/test-suite/ruby/director_unwrap_result_runme.rb b/Examples/test-suite/ruby/director_unwrap_result_runme.rb new file mode 100644 index 000000000..56970b3e8 --- /dev/null +++ b/Examples/test-suite/ruby/director_unwrap_result_runme.rb @@ -0,0 +1,106 @@ +#!/usr/bin/env ruby +# +# This test checks the proper unwrapping of director objects before returning +# a pointer to the (wrapped) instance. +# Unwrapping must not happen for return-by-value and returning higher +# reference levels (pointer to pointer, reference to pointer, etc.), but this +# is already checked by the C++ compiler. +# + +require 'swig_assert' + +require 'director_unwrap_result' + +############################ +# test with a regular (non-template) class + +class MyElement < Director_unwrap_result::Element +end + +class MyStorage < Director_unwrap_result::Storage + def initialize(e) + super() + @elem = e + end + def getIt + @elem.getPtrPtr + end +end + +e = MyElement.new +s = MyStorage.new(e) + +swig_assert_equal('s.getElement.class', 'Director_unwrap_result::Element', binding) +swig_assert('s.getElement != e', binding) + +# this shows that the director class was unwrapped: +swig_assert_equal('s.getElementPtr.class', 'MyElement', binding) +swig_assert_equal('s.getElementPtr', 'e', binding) + +# this shows that the director class was unwrapped: +swig_assert_equal('s.getElementRef.class', 'MyElement', binding) +swig_assert_equal('s.getElementRef', 'e', binding) + +swig_assert_equal('s.getElementPtrPtr.class', 'SWIG::TYPE_p_p_Element', binding) +swig_assert_equal('s.getElementPtrPtr.class', 'SWIG::TYPE_p_p_Element', binding) + +swig_assert_equal('s.getElementPtrRef.class', 'SWIG::TYPE_p_p_Element', binding) +swig_assert_equal('s.getElementPtrRef.class', 'SWIG::TYPE_p_p_Element', binding) + +############################ +# test with a template class + +class MyElementStorage < Director_unwrap_result::ElementStorage + def initialize(e) + super() + @elem = e + end + def getIt + @elem + end +end + +class MyElementPtrStorage < Director_unwrap_result::ElementPtrStorage + def initialize(e) + super() + @elem = e + end + def getIt + @elem.getPtrPtr + end +end + +class MyElementPtrPtrStorage < Director_unwrap_result::ElementPtrPtrStorage + def initialize(e) + super() + @elem = e + end + def getIt + @elem.getPtrPtrPtr + end +end + +e = MyElement.new + +s = MyElementStorage.new(e) +swig_assert_equal('s.getVal.class', 'Director_unwrap_result::Element', binding) +swig_assert('s.getVal != e', binding) +# this shows that the director class was unwrapped: +swig_assert_equal('s.getPtr.class', 'MyElement', binding) +swig_assert_equal('s.getPtr', 'e', binding) +# this shows that the director class was unwrapped: +swig_assert_equal('s.getRef.class', 'MyElement', binding) +swig_assert_equal('s.getRef', 'e', binding) + +s = MyElementPtrStorage.new(e) +# this shows that the director class was unwrapped: +swig_assert_equal('s.getVal.class', 'MyElement', binding) +swig_assert_equal('s.getVal', 'e', binding) +swig_assert_equal('s.getPtr.class', 'SWIG::TYPE_p_p_Element', binding) +swig_assert_equal('s.getRef.class', 'SWIG::TYPE_p_p_Element', binding) + +s = MyElementPtrPtrStorage.new(e) +swig_assert_equal('s.getVal.class', 'SWIG::TYPE_p_p_Element', binding) +swig_assert_equal('s.getPtr.class', 'SWIG::TYPE_p_p_p_Element', binding) +swig_assert_equal('s.getRef.class', 'SWIG::TYPE_p_p_p_Element', binding) + -- cgit v1.2.1