mirror of https://github.com/swig/swig
Python STL container method overloading fix
Fix method overloading of methods that take STL containers of different types. Due to some error handling that was not cleared during typehecking.
This commit is contained in:
parent
87bf8ae7aa
commit
86cb3a9532
|
@ -7,6 +7,56 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/
|
|||
Version 4.0.1 (in progress)
|
||||
===========================
|
||||
|
||||
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
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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>")
|
|
@ -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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -672,20 +672,14 @@ 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -395,20 +395,14 @@ 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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue