Fix overloading of shared_ptr method overloading

Add 'equivalent' attribute to typecheck typemap.
Closes #1098.
This commit is contained in:
William S Fulton 2017-09-23 14:46:44 +01:00
parent f5e1856650
commit ed4b84f4d3
24 changed files with 378 additions and 15 deletions

View File

@ -7,6 +7,36 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/
Version 4.0.0 (in progress)
===========================
2017-09-23: wsfulton
Issue #1098. Fix overloading of shared_ptr with underlying pointer types, eg:
void m(std::shared_ptr<T> p);
void m(T &p);
void m(T *p);
Only the first method is wrapped and the others are ignored/shadowed.
The implementation is done via a new attribute in the 'typecheck' typemap called
'equivalent'. If specified, it must contain the equivalent pointer type for overloading
and can only be used for the special SWIG_TYPECHECK_POINTER precedence level.
The shared_ptr 'typecheck' typemaps have been modified accordingly.
Here is a simplified version:
%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="T *")
T,
T CONST &,
T CONST *,
T *CONST&,
std::shared_ptr< T >,
std::shared_ptr< T > &,
std::shared_ptr< T > *,
std::shared_ptr< T > *&
{ ... }
Overloading with any of these types will result in SWIG ignoring all but the first
overloaded method by default. Without the 'equivalent' attribute, wrapping the overloaded
methods resulted in types being shadowed (scripting languages) or code that did not
compile (statically typed languages).
2017-09-19: futatuki
[Python] #1003 Add --with-2to3=/path/to/2to3 option to configure.

View File

@ -381,6 +381,7 @@
<ul>
<li><a href="Library.html#Library_shared_ptr_basics">shared_ptr basics</a>
<li><a href="Library.html#Library_shared_ptr_inheritance">shared_ptr and inheritance</a>
<li><a href="Library.html#Library_shared_ptr_overloading">shared_ptr and method overloading</a>
<li><a href="Library.html#Library_shared_ptr_templates">shared_ptr and templates</a>
<li><a href="Library.html#Library_shared_ptr_directors">shared_ptr and directors</a>
</ul>
@ -500,6 +501,9 @@
<li><a href="Typemaps.html#Typemaps_runtime_type_checker_usage">Usage</a>
</ul>
<li><a href="Typemaps.html#Typemaps_overloading">Typemaps and overloading</a>
<ul>
<li><a href="Typemaps.html#Typemaps_typecheck_pointer">SWIG_TYPECHECK_POINTER precedence level and the typecheck typemap</a>
</ul>
<li><a href="Typemaps.html#Typemaps_nn48">More about %apply and %clear</a>
<li><a href="Typemaps.html#Typemaps_nn47">Passing data between typemaps</a>
<li><a href="Typemaps.html#Typemaps_nn52">C++ "this" pointer</a>

View File

@ -35,6 +35,7 @@
<ul>
<li><a href="#Library_shared_ptr_basics">shared_ptr basics</a>
<li><a href="#Library_shared_ptr_inheritance">shared_ptr and inheritance</a>
<li><a href="#Library_shared_ptr_overloading">shared_ptr and method overloading</a>
<li><a href="#Library_shared_ptr_templates">shared_ptr and templates</a>
<li><a href="#Library_shared_ptr_directors">shared_ptr and directors</a>
</ul>
@ -1921,7 +1922,30 @@ Adding the missing <tt>%shared_ptr</tt> macros will fix this:
</pre>
</div>
<H4><a name="Library_shared_ptr_templates">9.4.4.3 shared_ptr and templates</a></H4>
<H4><a name="Library_shared_ptr_overloading">9.4.4.3 shared_ptr and method overloading</a></H4>
<p>
A C++ compiler can disambiguate a method overloaded by a shared_ptr and one using the raw underlying type.
For example, either one of these methods can be called in C++:
</p>
<div class="code">
<pre>
int age(std::shared_ptr&lt;GrandParent&gt; num);
int age(GrandParent&amp; num);
</pre>
</div>
<p>
When wrapped by SWIG, disambiguation is not possible using the overloaded names as there is just one equivalent type (<tt>GrandParent</tt>) in the target language.
SWIG will choose to wrap just the first method by default.
<a href="SWIGPlus.html#SWIGPlus_nn25">Ambiguity in overloading</a> discusses ways to control which method(s) gets wrapped using <tt>%ignore</tt> or <tt>%rename</tt>.
For the interested reader, SWIG detects that they are equivalent types via the <a href=Typemaps.html#Typemaps_typecheck_pointer>typecheck typemaps</a> in the shared_ptr library.
</p>
<H4><a name="Library_shared_ptr_templates">9.4.4.4 shared_ptr and templates</a></H4>
<p>
The <tt>%shared_ptr</tt> macro should be used for all the required instantiations
@ -1962,7 +1986,7 @@ The SWIG code below shows the required ordering:
</pre>
</div>
<H4><a name="Library_shared_ptr_directors">9.4.4.4 shared_ptr and directors</a></H4>
<H4><a name="Library_shared_ptr_directors">9.4.4.5 shared_ptr and directors</a></H4>
<p>

View File

@ -89,6 +89,9 @@
<li><a href="#Typemaps_runtime_type_checker_usage">Usage</a>
</ul>
<li><a href="#Typemaps_overloading">Typemaps and overloading</a>
<ul>
<li><a href="#Typemaps_typecheck_pointer">SWIG_TYPECHECK_POINTER precedence level and the typecheck typemap</a>
</ul>
<li><a href="#Typemaps_nn48">More about %apply and %clear</a>
<li><a href="#Typemaps_nn47">Passing data between typemaps</a>
<li><a href="#Typemaps_nn52">C++ "this" pointer</a>
@ -4754,7 +4757,8 @@ then the type is given a precedence higher than any other known precedence level
<div class="shell">
<pre>
example.i:18: Warning 467: Overloaded method foo(int) not supported (incomplete type checking rule - no precedence level in typecheck typemap for 'int').
example.i:18: Warning 467: Overloaded method foo(int) not supported (incomplete type
checking rule - no precedence level in typecheck typemap for 'int').
</pre>
</div>
@ -4779,10 +4783,112 @@ simply check the type of the first array element and use that to dispatch to the
Subsequent "in" typemaps would then perform more extensive type-checking.
</li>
<li>Make sure you read the section on overloading in the "<a href="SWIGPlus.html#SWIGPlus">SWIG and C++</a>" chapter.
<li>Make sure you read the section on <a href="SWIGPlus.html#SWIGPlus_overloaded_methods">overloading</a> in the SWIG and C++ chapter.
</li>
</ul>
<H3><a name="Typemaps_typecheck_pointer">11.13.1 SWIG_TYPECHECK_POINTER precedence level and the typecheck typemap</a></H3>
<p>
When it comes to overloading of a particular type passed by value, pointer or reference (const and non-const),
a C++ compiler can disambiguate which overloaded function to call.
However, SWIG effectively treats these as pointers in the target language and thus as equivalent types.
For example, consider:
</p>
<div class="code">
<pre>
class X { ... };
void m(X const &amp;c); // equivalent: void m(X *c);
void m(X &amp;r); // equivalent: void m(X *r);
void m(X *p); // equivalent: void m(X *p);
</pre>
</div>
<p>
These cannot be disambiguated in the target languages and so SWIG will choose the first method and ignore the subsequent two methods.
The scripting languages do this by using the overload dispatch mechanism described earlier and warnings indicate this:
</p>
<div class="shell">
<pre>
example.i:6: Warning 509: Overloaded method m(X &amp;) effectively ignored,
example.i:5: Warning 509: as it is shadowed by m(X const &amp;).
example.i:7: Warning 509: Overloaded method m(X *) effectively ignored,
example.i:5: Warning 509: as it is shadowed by m(X const &amp;).
</pre>
</div>
<p>
The statically typed languages like Java and C# automatically ignore all but the first equivalent overloaded methods with warnings:
</p>
<div class="shell">
<pre>
example.i:6: Warning 516: Overloaded method m(X &amp;) ignored,
example.i:5: Warning 516: using m(X const &amp;) instead.
example.i:7: Warning 516: Overloaded method m(X *) ignored,
example.i:5: Warning 516: using m(X const &amp;) instead.
</pre>
</div>
<p>
You can select the overloaded method you would like to wrap by ignoring the other two with <tt>%ignore</tt> or rename two of them with <tt>%rename</tt>
and this will of course remove the warnings too.
The problem of ambiguity is also discussed in the C++ chapter on <a href="SWIGPlus.html#SWIGPlus_overloaded_methods">overloading</a>.
</p>
<p>
So how does this work with respect to typemaps?
The typemaps SWIG provides to handle overloading for these three methods are from the SWIGTYPE family.
As discussed earlier, in <a href="Typemaps.html#Typemaps_nn19">Default typemap matching rules</a>,
the <tt>SWIGTYPE &amp;</tt> typemaps are used for references and <tt>SWIGTYPE *</tt> typemaps are used for pointers.
SWIG uses the special <tt>SWIG_TYPECHECK_POINTER</tt> (0) precedence level to handle these types in the "typecheck" typemap:
</p>
<div class="code">
<pre>
%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER) SWIGTYPE &amp; "..."
%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER) SWIGTYPE * "..."
</pre>
</div>
<p>
When the SWIGTYPE "typecheck" typemaps use the <tt>SWIG_TYPECHECK_POINTER</tt> precedence level,
SWIG converts the type to a pointer equivalent type and then uses the equivalent type to detect if it can be disambiguated in an overloaded method in the target language.
In our example above, the equivalent types for <tt>X const &amp;</tt>, <tt>X &amp;</tt> and <tt>X *</tt> are all <tt>X *</tt>.
As they are the same, they cannot be disambiguated and so just the first overloaded method is chosen.
</p>
<p>
The automatic conversion to equivalent types and subsequent type comparison is triggered via the use of the special <tt>SWIG_TYPECHECK_POINTER</tt> precedence level
and works for types passed by value, pointer and reference.
Alas, there are more ways to overload a method that also need handling.
C++ smart pointers are such a type which can be disambiguated by a C++ compiler but not automatically by SWIG.
SWIG does not automatically know that a smart pointer has an equivalent type, but it can be told manually.
Just specify the 'equivalent' attribute in the "typecheck" typemap with a pointer to the underlying type.
</p>
<div class="code">
<pre>
%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="X *") MySmartPtr&lt;X&gt; " ... "
void m(X &amp;r); // equivalent: void m(X *r);
void m(MySmartPtr&lt;X&gt; s); // equivalent: void m(X *s);
</pre>
</div>
<p>
Now SWIG will detect the two types are equivalent and generate valid code by wrapping just the first overloaded method.
You can of course choose which method to wrap by ignoring one of them with <tt>%ignore</tt>.
Otherwise both can be wrapped by removing the overloading name ambiguity by renaming one of them with <tt>%rename</tt>.
</p>
<p>
The 'equivalent' attribute is used in the implementation for the <a href="Library.html#Library_std_shared_ptr">shared_ptr smart pointer</a> library.
</p>
<H2><a name="Typemaps_nn48">11.14 More about %apply and %clear</a></H2>

View File

@ -31,6 +31,7 @@ CPP_TEST_CASES = \
CPP11_TEST_CASES = \
cpp11_shared_ptr_const \
cpp11_shared_ptr_nullptr_in_containers \
cpp11_shared_ptr_overload \
cpp11_shared_ptr_upcast \
cpp11_strongly_typed_enumerations_simple \

View File

@ -27,6 +27,7 @@ CPP_TEST_CASES = \
CPP11_TEST_CASES = \
cpp11_shared_ptr_const \
cpp11_shared_ptr_nullptr_in_containers \
cpp11_shared_ptr_overload \
cpp11_shared_ptr_upcast \
include $(srcdir)/../common.mk

View File

@ -46,6 +46,7 @@ CPP_TEST_CASES = \
CPP11_TEST_CASES = \
cpp11_shared_ptr_const \
cpp11_shared_ptr_nullptr_in_containers \
cpp11_shared_ptr_overload \
cpp11_shared_ptr_upcast \
cpp11_strongly_typed_enumerations_simple \

View File

@ -0,0 +1,60 @@
import cpp11_shared_ptr_overload.*;
public class cpp11_shared_ptr_overload_runme {
static {
try {
System.loadLibrary("cpp11_shared_ptr_overload");
} 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[])
{
String ret = null;
// ref
ret = cpp11_shared_ptr_overload.UseA(new MyType("123"));
if (!ret.equals("123 ref")) throw new RuntimeException("UseA fail:" + ret);
ret = cpp11_shared_ptr_overload.UseB(0, new MyType("123"));
if (!ret.equals("123 ref")) throw new RuntimeException("UseB fail:" + ret);
ret = cpp11_shared_ptr_overload.UseC(0, new MyType("123"), new MyType("456"));
if (!ret.equals("123 ref")) throw new RuntimeException("UseC fail:" + ret);
// sharedptr
ret = cpp11_shared_ptr_overload.UseX(new MyType("123"));
if (!ret.equals("123 sharedptr")) throw new RuntimeException("UseX fail:" + ret);
ret = cpp11_shared_ptr_overload.UseY(0, new MyType("123"));
if (!ret.equals("123 sharedptr")) throw new RuntimeException("UseY fail:" + ret);
ret = cpp11_shared_ptr_overload.UseZ(0, new MyType("123"), new MyType("456"));
if (!ret.equals("123 sharedptr")) throw new RuntimeException("UseZ fail:" + ret);
// Combo1-4
ret = cpp11_shared_ptr_overload.Combo1(new MyType("XXX"));
if (!ret.equals("XXXCombo1")) throw new RuntimeException("Combo1 fail:" + ret);
ret = cpp11_shared_ptr_overload.Combo2(new MyType("XXX"));
if (!ret.equals("XXXCombo2")) throw new RuntimeException("Combo2 fail:" + ret);
ret = cpp11_shared_ptr_overload.Combo3(new MyType("XXX"));
if (!ret.equals("XXXCombo3")) throw new RuntimeException("Combo3 fail:" + ret);
ret = cpp11_shared_ptr_overload.Combo4(new MyType("XXX"));
if (!ret.equals("XXXCombo4")) throw new RuntimeException("Combo4 fail:" + ret);
// Combo5-7
ret = cpp11_shared_ptr_overload.Combo5(new MyType("XXX"));
if (!ret.equals("XXXCombo5")) throw new RuntimeException("Combo5 fail:" + ret);
ret = cpp11_shared_ptr_overload.Combo6(new MyType("XXX"));
if (!ret.equals("XXXCombo6")) throw new RuntimeException("Combo6 fail:" + ret);
ret = cpp11_shared_ptr_overload.Combo7(new MyType("XXX"));
if (!ret.equals("XXXCombo7")) throw new RuntimeException("Combo7 fail:" + ret);
}
}

View File

@ -83,6 +83,7 @@ CPP11_TEST_CASES = \
cpp11_hash_tables \
cpp11_shared_ptr_const \
cpp11_shared_ptr_nullptr_in_containers \
cpp11_shared_ptr_overload \
cpp11_shared_ptr_upcast \
C_TEST_CASES += \

View File

@ -0,0 +1,45 @@
import cpp11_shared_ptr_overload
from cpp11_shared_ptr_overload import MyType
# ref
ret = cpp11_shared_ptr_overload.UseA(MyType("123"))
if ret != "123 ref": raise RuntimeError("UseA fail:" + ret)
ret = cpp11_shared_ptr_overload.UseB(0, MyType("123"))
if ret != "123 ref": raise RuntimeError("UseB fail:" + ret)
ret = cpp11_shared_ptr_overload.UseC(0, MyType("123"), MyType("456"))
if ret != "123 ref": raise RuntimeError("UseC fail:" + ret)
# sharedptr
ret = cpp11_shared_ptr_overload.UseX(MyType("123"))
if ret != "123 sharedptr": raise RuntimeError("UseX fail:" + ret)
ret = cpp11_shared_ptr_overload.UseY(0, MyType("123"))
if ret != "123 sharedptr": raise RuntimeError("UseY fail:" + ret)
ret = cpp11_shared_ptr_overload.UseZ(0, MyType("123"), MyType("456"))
if ret != "123 sharedptr": raise RuntimeError("UseZ fail:" + ret)
# Combo1-4
ret = cpp11_shared_ptr_overload.Combo1(MyType("XXX"))
if ret != "XXXCombo1": raise RuntimeError("Combo1 fail:" + ret)
ret = cpp11_shared_ptr_overload.Combo2(MyType("XXX"))
if ret != "XXXCombo2": raise RuntimeError("Combo2 fail:" + ret)
ret = cpp11_shared_ptr_overload.Combo3(MyType("XXX"))
if ret != "XXXCombo3": raise RuntimeError("Combo3 fail:" + ret)
ret = cpp11_shared_ptr_overload.Combo4(MyType("XXX"))
if ret != "XXXCombo4": raise RuntimeError("Combo4 fail:" + ret)
# Combo5-7
ret = cpp11_shared_ptr_overload.Combo5(MyType("XXX"))
if ret != "XXXCombo5": raise RuntimeError("Combo5 fail:" + ret)
ret = cpp11_shared_ptr_overload.Combo6(MyType("XXX"))
if ret != "XXXCombo6": raise RuntimeError("Combo6 fail:" + ret)
ret = cpp11_shared_ptr_overload.Combo7(MyType("XXX"))
if ret != "XXXCombo7": raise RuntimeError("Combo7 fail:" + ret)

View File

@ -36,6 +36,7 @@ CPP11_TEST_CASES = \
cpp11_hash_tables \
cpp11_shared_ptr_const \
cpp11_shared_ptr_nullptr_in_containers \
cpp11_shared_ptr_overload \
cpp11_shared_ptr_upcast \
cpp11_std_unordered_map \
cpp11_std_unordered_multimap \

View File

@ -505,6 +505,17 @@
%typemap(imtype, nopgcpp="1") SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > swigSharedPtrUpcast "global::System.Runtime.InteropServices.HandleRef"
%typemap(imtype, nopgcpp="1") SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > swigSharedPtrUpcast "global::System.Runtime.InteropServices.HandleRef"
// Typecheck typemaps
%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *")
TYPE CONST,
TYPE CONST &,
TYPE CONST *,
TYPE *CONST&,
SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >,
SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &,
SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *,
SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *&
""
%template() SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >;
%enddef

View File

@ -233,6 +233,18 @@
}
}
// Typecheck typemaps
%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *")
TYPE CONST,
TYPE CONST &,
TYPE CONST *,
TYPE *CONST&,
SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >,
SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &,
SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *,
SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *&
""
%template() SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >;
%enddef

View File

@ -197,5 +197,17 @@ public static void* swigGetCPtr(typeof(this) obj) {
}
}
// Typecheck typemaps
%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *")
TYPE CONST,
TYPE CONST &,
TYPE CONST *,
TYPE *CONST&,
SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >,
SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &,
SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *,
SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *&
""
%template() SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >;
%enddef

View File

@ -467,6 +467,17 @@
%typemap(jtype, nopgcpp="1") SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< TYPE > swigSharedPtrUpcast "long"
%typemap(jtype, nopgcpp="1") SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > swigSharedPtrUpcast "long"
// Typecheck typemaps
%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *")
TYPE CONST,
TYPE CONST &,
TYPE CONST *,
TYPE *CONST&,
SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >,
SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &,
SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *,
SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *&
""
%template() SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >;
%enddef

View File

@ -225,6 +225,18 @@
}
%}
// Typecheck typemaps
%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *")
TYPE CONST,
TYPE CONST &,
TYPE CONST *,
TYPE *CONST&,
SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >,
SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > &,
SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *,
SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *&
""
%template() SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >;
%enddef

View File

@ -283,7 +283,7 @@
// Typecheck typemaps
// Note: SWIG_ConvertPtr with void ** parameter set to 0 instead of using SWIG_ConvertPtrAndOwn, so that the casting
// function is not called thereby avoiding a possible smart pointer copy constructor call when casting up the inheritance chain.
%typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER,noblock=1)
%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1)
TYPE CONST,
TYPE CONST &,
TYPE CONST *,

View File

@ -294,7 +294,7 @@
// Typecheck typemaps
// Note: SWIG_ConvertPtr with void ** parameter set to 0 instead of using SWIG_ConvertPtrAndOwn, so that the casting
// function is not called thereby avoiding a possible smart pointer copy constructor call when casting up the inheritance chain.
%typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER,noblock=1)
%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1)
TYPE CONST,
TYPE CONST &,
TYPE CONST *,

View File

@ -281,7 +281,7 @@
// Typecheck typemaps
// Note: SWIG_ConvertPtr with void ** parameter set to 0 instead of using SWIG_ConvertPtrAndOwn, so that the casting
// function is not called thereby avoiding a possible smart pointer copy constructor call when casting up the inheritance chain.
%typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER,noblock=1)
%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1)
TYPE CONST,
TYPE CONST &,
TYPE CONST *,

View File

@ -369,7 +369,7 @@
// Typecheck typemaps
// Note: SWIG_ConvertPtr with void ** parameter set to 0 instead of using SWIG_ConvertPtrAndOwn, so that the casting
// function is not called thereby avoiding a possible smart pointer copy constructor call when casting up the inheritance chain.
%typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER,noblock=1)
%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1)
TYPE CONST,
TYPE CONST &,
TYPE CONST *,

View File

@ -3,7 +3,7 @@
%include <rubystdcommon_forward.swg>
%fragment("StdSharedPtrTraits","header",fragment="StdTraitsForwardDeclaration")
%fragment("StdSharedPtrTraits","header",fragment="StdTraitsForwardDeclaration",fragment="<memory>")
{
namespace swig {
/*

View File

@ -290,7 +290,7 @@
// Typecheck typemaps
// Note: SWIG_ConvertPtr with void ** parameter set to 0 instead of using SWIG_ConvertPtrAndOwn, so that the casting
// function is not called thereby avoiding a possible smart pointer copy constructor call when casting up the inheritance chain.
%typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER,noblock=1)
%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1)
TYPE CONST,
TYPE CONST &,
TYPE CONST *,

View File

@ -12,6 +12,7 @@
* ----------------------------------------------------------------------------- */
#include "swigmod.h"
#include "cparse.h"
/* -----------------------------------------------------------------------------
* emit_return_variable()
@ -112,9 +113,8 @@ void emit_attach_parmmaps(ParmList *l, Wrapper *f) {
/* This is compatibility code to deal with the deprecated "ignore" typemap */
Parm *p = l;
Parm *np;
String *tm;
while (p) {
tm = Getattr(p, "tmap:in");
String *tm = Getattr(p, "tmap:in");
if (tm && checkAttribute(p, "tmap:in:numinputs", "0")) {
Replaceall(tm, "$target", Getattr(p, "lname"));
Printv(f->code, tm, "\n", NIL);
@ -134,7 +134,6 @@ void emit_attach_parmmaps(ParmList *l, Wrapper *f) {
/* Perform a sanity check on "in" and "freearg" typemaps. These
must exactly match to avoid chaos. If a mismatch occurs, we
nuke the freearg typemap */
{
Parm *p = l;
Parm *npin, *npfreearg;
@ -196,6 +195,36 @@ void emit_attach_parmmaps(ParmList *l, Wrapper *f) {
}
}
}
/*
* An equivalent type can be used in the typecheck typemap for SWIG to detect the overloading of equivalent
* target language types. This is primarily for the smartptr feature, where a pointer and a smart pointer
* are seen as equivalent types in the target language.
*/
{
Parm *p = l;
while (p) {
String *tm = Getattr(p, "tmap:typecheck");
if (tm) {
String *equivalent = Getattr(p, "tmap:typecheck:equivalent");
if (equivalent) {
String *precedence = Getattr(p, "tmap:typecheck:precedence");
if (precedence && Strcmp(precedence, "0") != 0)
Swig_error(Getfile(tm), Getline(tm), "The 'typecheck' typemap for %s contains an 'equivalent' attribute for a 'precedence' that is not set to SWIG_TYPECHECK_POINTER or 0.\n", SwigType_str(Getattr(p, "type"), 0));
SwigType *cpt = Swig_cparse_type(equivalent);
if (cpt) {
Setattr(p, "equivtype", cpt);
Delete(cpt);
} else {
Swig_error(Getfile(tm), Getline(tm), "Invalid type (%s) in 'equivalent' attribute in 'typecheck' typemap for type %s.\n", equivalent, SwigType_str(Getattr(p, "type"), 0));
}
}
p = Getattr(p, "tmap:typecheck:next");
} else {
p = nextSibling(p);
}
}
}
}
/* -----------------------------------------------------------------------------

View File

@ -185,7 +185,8 @@ List *Swig_overload_rank(Node *n, bool script_lang_wrapping) {
nodes[j] = t;
break;
} else if ((differ == 0) && (Strcmp(t1, "0") == 0)) {
t1 = Getattr(p1, "ltype");
t1 = Getattr(p1, "equivtype");
t1 = t1 ? t1 : Getattr(p1, "ltype");
if (!t1) {
t1 = SwigType_ltype(Getattr(p1, "type"));
if (Getattr(p1, "tmap:typecheck:SWIGTYPE")) {
@ -193,7 +194,8 @@ List *Swig_overload_rank(Node *n, bool script_lang_wrapping) {
}
Setattr(p1, "ltype", t1);
}
t2 = Getattr(p2, "ltype");
t2 = Getattr(p2, "equivtype");
t2 = t2 ? t2 : Getattr(p2, "ltype");
if (!t2) {
t2 = SwigType_ltype(Getattr(p2, "type"));
if (Getattr(p2, "tmap:typecheck:SWIGTYPE")) {