Merge branch 'python-stl-overloading'
* python-stl-overloading: Python STL container method overloading fix
This commit is contained in:
commit
5e2b8f3ec9
9 changed files with 200 additions and 24 deletions
|
|
@ -10,6 +10,56 @@ Version 4.0.1 (in progress)
|
||||||
2019-08-08: rokups
|
2019-08-08: rokups
|
||||||
[C#, Java] #1601 Fix invalid code generated for "%constant enum EnumType.
|
[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
|
2019-08-01: wsfulton
|
||||||
#1602 Fix regression in 4.0.0 where a template function containing a parameter
|
#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
|
with the same name as the function name led to the parameter name used in the
|
||||||
|
|
|
||||||
|
|
@ -643,6 +643,7 @@ CPP_STD_TEST_CASES += \
|
||||||
director_string \
|
director_string \
|
||||||
ignore_template_constructor \
|
ignore_template_constructor \
|
||||||
li_std_combinations \
|
li_std_combinations \
|
||||||
|
li_std_containers_overload \
|
||||||
li_std_deque \
|
li_std_deque \
|
||||||
li_std_except \
|
li_std_except \
|
||||||
li_std_except_as_class \
|
li_std_except_as_class \
|
||||||
|
|
|
||||||
33
Examples/test-suite/li_std_containers_overload.i
Normal file
33
Examples/test-suite/li_std_containers_overload.i
Normal file
|
|
@ -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>";
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
|
@ -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>");
|
||||||
|
|
@ -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>")
|
||||||
44
Examples/test-suite/ruby/li_std_containers_overload_runme.rb
Normal file
44
Examples/test-suite/ruby/li_std_containers_overload_runme.rb
Normal file
|
|
@ -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>")
|
||||||
|
|
@ -401,21 +401,15 @@ namespace swig
|
||||||
return const_reference(_seq, n);
|
return const_reference(_seq, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool check(bool set_err = true) const
|
bool check() const
|
||||||
{
|
{
|
||||||
int s = size();
|
int s = size();
|
||||||
for (int i = 0; i < s; ++i) {
|
for (int i = 0; i < s; ++i) {
|
||||||
// swig::SwigVar_PyObject item = OctSequence_GetItem(_seq, i);
|
// swig::SwigVar_PyObject item = OctSequence_GetItem(_seq, i);
|
||||||
octave_value item; // * todo
|
octave_value item; // * todo
|
||||||
if (!swig::check<value_type>(item)) {
|
if (!swig::check<value_type>(item))
|
||||||
if (set_err) {
|
|
||||||
char msg[1024];
|
|
||||||
sprintf(msg, "in sequence element %d", i);
|
|
||||||
SWIG_Error(SWIG_RuntimeError, msg);
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -672,20 +672,14 @@ namespace swig
|
||||||
return const_reference(_seq, n);
|
return const_reference(_seq, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool check(bool set_err = true) const
|
bool check() const
|
||||||
{
|
{
|
||||||
Py_ssize_t s = size();
|
Py_ssize_t s = size();
|
||||||
for (Py_ssize_t i = 0; i < s; ++i) {
|
for (Py_ssize_t i = 0; i < s; ++i) {
|
||||||
swig::SwigVar_PyObject item = PySequence_GetItem(_seq, i);
|
swig::SwigVar_PyObject item = PySequence_GetItem(_seq, i);
|
||||||
if (!swig::check<value_type>(item)) {
|
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);
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -395,20 +395,14 @@ namespace swig
|
||||||
return const_reference(_seq, n);
|
return const_reference(_seq, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool check(bool set_err = false) const
|
bool check() const
|
||||||
{
|
{
|
||||||
int s = (int) size();
|
int s = (int) size();
|
||||||
for (int i = 0; i < s; ++i) {
|
for (int i = 0; i < s; ++i) {
|
||||||
VALUE item = rb_ary_entry(_seq, i );
|
VALUE item = rb_ary_entry(_seq, i );
|
||||||
if (!swig::check<value_type>(item)) {
|
if (!swig::check<value_type>(item))
|
||||||
if (set_err) {
|
|
||||||
char msg[1024];
|
|
||||||
sprintf(msg, "in sequence element %d", i);
|
|
||||||
SWIG_Error(SWIG_RuntimeError, msg);
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue