aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam S Fulton <wsf@fultondesigns.co.uk>2019-08-08 18:58:49 +0100
committerWilliam S Fulton <wsf@fultondesigns.co.uk>2019-08-08 18:58:49 +0100
commit5e2b8f3ec9594b385824976ebf79b22572d06214 (patch)
treefab7f3fd6b4226da889ee3371fd0c863cbf33b10
parentbef1fab3e6c2198bc241698ae2341b6ce7d0043b (diff)
parent86cb3a953230c6c63bf38579a44955b2b5084eaf (diff)
downloadswig-5e2b8f3ec9594b385824976ebf79b22572d06214.tar.gz
Merge branch 'python-stl-overloading'
* python-stl-overloading: Python STL container method overloading fix
-rw-r--r--CHANGES.current50
-rw-r--r--Examples/test-suite/common.mk1
-rw-r--r--Examples/test-suite/li_std_containers_overload.i33
-rw-r--r--Examples/test-suite/octave/li_std_containers_overload_runme.m37
-rw-r--r--Examples/test-suite/python/li_std_containers_overload_runme.py29
-rw-r--r--Examples/test-suite/ruby/li_std_containers_overload_runme.rb44
-rw-r--r--Lib/octave/octcontainer.swg10
-rw-r--r--Lib/python/pycontainer.swg10
-rw-r--r--Lib/ruby/rubycontainer.swg10
9 files changed, 200 insertions, 24 deletions
diff --git a/CHANGES.current b/CHANGES.current
index 742035683..53c409773 100644
--- a/CHANGES.current
+++ b/CHANGES.current
@@ -10,6 +10,56 @@ Version 4.0.1 (in progress)
2019-08-08: rokups
[C#, Java] #1601 Fix invalid code generated for "%constant enum EnumType.
+2019-08-07: wsfulton
+ [Python] Fix method overloading of methods that take STL containers of different
+ types. The following usage (using std::vector) would fail when using -builtin:
+
+ %include <std_string.i>
+ %include <std_vector.i>
+
+ %inline %{
+ struct X {};
+ %}
+
+ %template(VectorX) std::vector<X>;
+ %template(VectorInt) std::vector<int>;
+
+ %inline %{
+ using namespace std;
+ string VectorOverload(vector<X> v);
+ string VectorOverload(vector<int> v);
+ %}
+
+ The following would incorrectly fail:
+
+ s = VectorOverload([1, 2, 3])
+
+ With:
+
+ Traceback (most recent call last):
+ File "runme3.py", line 20, in <module>
+ ret = VectorOverload([1, 2, 3])
+ TypeError: Wrong number or type of arguments for overloaded function 'VectorOverload'.
+ Possible C/C++ prototypes are:
+ VectorOverload(std::vector< Number,std::allocator< Number > >)
+ VectorOverload(std::vector< int,std::allocator< int > >)
+
+ The problem was due to some error handling that was not cleared during typehecking.
+ In this case an error was not cleared when the elements in the list failed the
+ typecheck for converting to X. Only occurs in Python 3+.
+
+ In some combinations of overloaded methods, the following type of error message would
+ occur:
+
+ RuntimeError: in sequence element 0
+
+ The above exception was the direct cause of the following exception:
+
+ Traceback (most recent call last):
+ File "runme3.py", line 23, in <module>
+ check(VectorOverload(v), "vector<X>")
+ SystemError: <built-in function VectorOverload> returned a result with an error set
+
2019-08-01: wsfulton
#1602 Fix regression in 4.0.0 where a template function containing a parameter
with the same name as the function name led to the parameter name used in the
diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk
index 7aa0e91d1..5f7792810 100644
--- a/Examples/test-suite/common.mk
+++ b/Examples/test-suite/common.mk
@@ -643,6 +643,7 @@ CPP_STD_TEST_CASES += \
director_string \
ignore_template_constructor \
li_std_combinations \
+ li_std_containers_overload \
li_std_deque \
li_std_except \
li_std_except_as_class \
diff --git a/Examples/test-suite/li_std_containers_overload.i b/Examples/test-suite/li_std_containers_overload.i
new file mode 100644
index 000000000..5e7c28e37
--- /dev/null
+++ b/Examples/test-suite/li_std_containers_overload.i
@@ -0,0 +1,33 @@
+%module li_std_containers_overload
+
+// Suppress warning that ought not to appear, but there is no easy fix
+%warnfilter(SWIGWARN_LANG_OVERLOAD_SHADOW) VectorOverload;
+
+%include <std_string.i>
+%include <std_vector.i>
+
+%inline %{
+struct X {};
+struct Y {};
+%}
+
+%template(VectorX) std::vector<X>;
+%template(VectorY) std::vector<Y>;
+%template(VectorString) std::vector<std::string>;
+%template(VectorInt) std::vector<int>;
+
+%inline %{
+using namespace std;
+string VectorOverload(vector<X> v) {
+ return "vector<X>";
+}
+string VectorOverload(vector<Y> v) {
+ return "vector<Y>";
+}
+string VectorOverload(vector<string> v) {
+ return "vector<string>";
+}
+string VectorOverload(vector<int> v) {
+ return "vector<int>";
+}
+%}
diff --git a/Examples/test-suite/octave/li_std_containers_overload_runme.m b/Examples/test-suite/octave/li_std_containers_overload_runme.m
new file mode 100644
index 000000000..786d63466
--- /dev/null
+++ b/Examples/test-suite/octave/li_std_containers_overload_runme.m
@@ -0,0 +1,37 @@
+# do not dump Octave core
+if exist("crash_dumps_octave_core", "builtin")
+ crash_dumps_octave_core(0);
+endif
+
+li_std_containers_overload
+
+function check(got, expected)
+ if (!strcmp(got, expected))
+ error("Failed check. '%s' != '%s'", got, expected)
+ endif
+end
+
+v = VectorX();
+check(VectorOverload(v), "vector<X>");
+
+v = VectorY();
+check(VectorOverload(v), "vector<Y>");
+
+v = VectorInt();
+check(VectorOverload(v), "vector<int>");
+
+v = VectorString();
+check(VectorOverload(v), "vector<string>");
+
+# TODO: Conversion from an Octave sequence not implemented yet
+# v = {X()};
+# check(VectorOverload(v), "vector<X>");
+
+# v = {Y()};
+# check(VectorOverload(v), "vector<Y>");
+
+# v = {1, 2, 3};
+# check(VectorOverload(v), "vector<int>");
+
+# v = {"aaa", "bbb", "ccc"};
+# check(VectorOverload(v), "vector<string>");
diff --git a/Examples/test-suite/python/li_std_containers_overload_runme.py b/Examples/test-suite/python/li_std_containers_overload_runme.py
new file mode 100644
index 000000000..dcb383511
--- /dev/null
+++ b/Examples/test-suite/python/li_std_containers_overload_runme.py
@@ -0,0 +1,29 @@
+from li_std_containers_overload import *
+
+def check(got, expected):
+ if got != expected:
+ raise RuntimeError("Failed check. '{}' != '{}'".format(got, expected))
+
+v = VectorX()
+check(VectorOverload(v), "vector<X>")
+
+v = VectorY()
+check(VectorOverload(v), "vector<Y>")
+
+v = VectorInt()
+check(VectorOverload(v), "vector<int>")
+
+v = VectorString()
+check(VectorOverload(v), "vector<string>")
+
+v = [X()]
+check(VectorOverload(v), "vector<X>")
+
+v = [Y()]
+check(VectorOverload(v), "vector<Y>")
+
+v = [1, 2, 3]
+check(VectorOverload(v), "vector<int>")
+
+v = ["aaa", "bbb", "ccc"]
+check(VectorOverload(v), "vector<string>")
diff --git a/Examples/test-suite/ruby/li_std_containers_overload_runme.rb b/Examples/test-suite/ruby/li_std_containers_overload_runme.rb
new file mode 100644
index 000000000..913b6113a
--- /dev/null
+++ b/Examples/test-suite/ruby/li_std_containers_overload_runme.rb
@@ -0,0 +1,44 @@
+#!/usr/bin/env ruby
+#
+# Put description here
+#
+#
+#
+#
+#
+
+require 'swig_assert'
+
+require 'li_std_containers_overload'
+
+include Li_std_containers_overload
+
+def check(got, expected)
+ if (got != expected)
+ raise RuntimeError, "Failed check. '#{got}' != '#{expected}'"
+ end
+end
+
+v = VectorX.new()
+check(VectorOverload(v), "vector<X>")
+
+v = VectorY.new()
+check(VectorOverload(v), "vector<Y>")
+
+v = VectorInt.new()
+check(VectorOverload(v), "vector<int>")
+
+v = VectorString.new()
+check(VectorOverload(v), "vector<string>")
+
+v = [X.new()]
+check(VectorOverload(v), "vector<X>")
+
+v = [Y.new()]
+check(VectorOverload(v), "vector<Y>")
+
+v = [1, 2, 3]
+check(VectorOverload(v), "vector<int>")
+
+v = ["aaa", "bbb", "ccc"]
+check(VectorOverload(v), "vector<string>")
diff --git a/Lib/octave/octcontainer.swg b/Lib/octave/octcontainer.swg
index 269ff7544..310a849d9 100644
--- a/Lib/octave/octcontainer.swg
+++ b/Lib/octave/octcontainer.swg
@@ -401,20 +401,14 @@ namespace swig
return const_reference(_seq, n);
}
- bool check(bool set_err = true) const
+ bool check() const
{
int s = size();
for (int i = 0; i < s; ++i) {
// swig::SwigVar_PyObject item = OctSequence_GetItem(_seq, i);
octave_value item; // * todo
- if (!swig::check<value_type>(item)) {
- if (set_err) {
- char msg[1024];
- sprintf(msg, "in sequence element %d", i);
- SWIG_Error(SWIG_RuntimeError, msg);
- }
+ if (!swig::check<value_type>(item))
return false;
- }
}
return true;
}
diff --git a/Lib/python/pycontainer.swg b/Lib/python/pycontainer.swg
index ef2f725af..fef4e9b3b 100644
--- a/Lib/python/pycontainer.swg
+++ b/Lib/python/pycontainer.swg
@@ -672,19 +672,13 @@ namespace swig
return const_reference(_seq, n);
}
- bool check(bool set_err = true) const
+ bool check() const
{
Py_ssize_t s = size();
for (Py_ssize_t i = 0; i < s; ++i) {
swig::SwigVar_PyObject item = PySequence_GetItem(_seq, i);
- if (!swig::check<value_type>(item)) {
- if (set_err) {
- char msg[1024];
- sprintf(msg, "in sequence element %d", (int)i);
- SWIG_Error(SWIG_RuntimeError, msg);
- }
+ if (!swig::check<value_type>(item))
return false;
- }
}
return true;
}
diff --git a/Lib/ruby/rubycontainer.swg b/Lib/ruby/rubycontainer.swg
index e8830a715..9fa205bf5 100644
--- a/Lib/ruby/rubycontainer.swg
+++ b/Lib/ruby/rubycontainer.swg
@@ -395,19 +395,13 @@ namespace swig
return const_reference(_seq, n);
}
- bool check(bool set_err = false) const
+ bool check() const
{
int s = (int) size();
for (int i = 0; i < s; ++i) {
VALUE item = rb_ary_entry(_seq, i );
- if (!swig::check<value_type>(item)) {
- if (set_err) {
- char msg[1024];
- sprintf(msg, "in sequence element %d", i);
- SWIG_Error(SWIG_RuntimeError, msg);
- }
+ if (!swig::check<value_type>(item))
return false;
- }
}
return true;
}