mirror of https://github.com/swig/swig
%apply and typedefs improvement
Perform repeated typedef lookups instead of a single typedef lookup on the type being applied in %apply when looking for a family of typemaps to apply. Closes #3064
This commit is contained in:
parent
40b6cc684f
commit
d9edb22d1c
|
@ -7,6 +7,11 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/
|
|||
Version 4.4.0 (in progress)
|
||||
===========================
|
||||
|
||||
2024-11-09: wsfulton
|
||||
#3064 Perform repeated typedef lookups instead of a single typedef
|
||||
lookup on the type being applied in %apply when looking for a family
|
||||
of typemaps to apply.
|
||||
|
||||
2024-11-01: wsfulton
|
||||
Fix internal error handling parameters that are typedefs to references
|
||||
when using the compactdefaultargs feature.
|
||||
|
|
|
@ -617,6 +617,9 @@
|
|||
<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>
|
||||
<ul>
|
||||
<li><a href="Typemaps.html#Typemaps_apply_typedefs">Typedefs and %apply</a>
|
||||
</ul>
|
||||
<li><a href="Typemaps.html#Typemaps_nn47">Passing data between typemaps</a>
|
||||
<li><a href="Typemaps.html#Typemaps_nn52">C++ "this" pointer</a>
|
||||
<li><a href="Typemaps.html#Typemaps_nn51">Where to go for more information?</a>
|
||||
|
|
|
@ -98,6 +98,9 @@
|
|||
<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>
|
||||
<ul>
|
||||
<li><a href="#Typemaps_apply_typedefs">Typedefs and %apply</a>
|
||||
</ul>
|
||||
<li><a href="#Typemaps_nn47">Passing data between typemaps</a>
|
||||
<li><a href="#Typemaps_nn52">C++ "this" pointer</a>
|
||||
<li><a href="#Typemaps_nn51">Where to go for more information?</a>
|
||||
|
@ -5104,7 +5107,6 @@ For example:
|
|||
%typemap(check) int *POSITIVE {
|
||||
if (*$1 <= 0) {
|
||||
SWIG_exception(SWIG_ValueError, "Expected a positive number!\n");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5144,6 +5146,88 @@ will delete the typemaps for all the typemap methods; namely "in", "check" and "
|
|||
</pre>
|
||||
</div>
|
||||
|
||||
<H3><a name="Typemaps_apply_typedefs">14.14.1 Typedefs and %apply</a></H3>
|
||||
|
||||
|
||||
<p>
|
||||
Consider a similar example to that shown earlier but this time with a couple of typedefs:
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
%typemap(check) int *NEGATIVE {
|
||||
if (*$1 >= 0) {
|
||||
SWIG_exception(SWIG_ValueError, "Expected a negative number!\n");
|
||||
}
|
||||
}
|
||||
|
||||
typedef int integer;
|
||||
typedef integer negative_integer;
|
||||
void fff(negative_integer *number);
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
Typically <tt>%apply</tt> is specified with the exact type <i>being applied</i>, such as <tt>int *</tt> in the following case:
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
%apply int *NEGATIVE { negative_integer *number };
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
to find an exact typemap match: <tt>int *NEGATIVE</tt>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
However, the following will also work in this case:
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
%apply negative_integer *NEGATIVE { negative_integer *number };
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
as SWIG will use the typedefs to find a match. Typemaps will be searched for until one matches by following the typedefs in the expected order:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li> <tt>negative_integer *NEGATIVE</tt>
|
||||
<li> <tt>integer *NEGATIVE</tt>
|
||||
<li> <tt>int *NEGATIVE</tt>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
Note that the search looks for a <b>family of typemaps</b> and will stop when a typemap with <b>any matching method name</b> is found.
|
||||
So for example, consider the addition of an "argout" typemap method to the example:
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
%typemap(argout) negative_integer *NEGATIVE {
|
||||
// return value somehow
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
There is then at least one typemap method creating a family of typemaps: <tt>negative_integer *NEGATIVE</tt>.
|
||||
As the search halts on the closest match when chasing typedefs,
|
||||
and this family of typemaps does not have a "check" typemap method, there is no "check" typemap method to apply.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
In summary, the addition of the better matching "argout" typemap
|
||||
for <tt>negative_integer *NEGATIVE</tt>
|
||||
introduces a new family of typemaps resulting in the previously matching "check" typemap
|
||||
for <tt>int *NEGATIVE</tt>
|
||||
no longer being available for applying.
|
||||
</p>
|
||||
|
||||
<H2><a name="Typemaps_nn47">14.15 Passing data between typemaps</a></H2>
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
%module apply_typemap_typedefs
|
||||
|
||||
%typemap(in) int "_this_will_not_compile_"
|
||||
%typemap(in) int OK "$1 = 10;" // (A)
|
||||
%typemap(in) Int1 OKAY "$1 = 20;" // (B)
|
||||
|
||||
%inline %{
|
||||
typedef int Int1;
|
||||
typedef Int1 Int2;
|
||||
typedef Int2 Int3;
|
||||
%}
|
||||
|
||||
%apply Int2 OK {Int2 i2} // applies (A) as 'Int2 OK' resolves to 'int OK'
|
||||
%inline %{
|
||||
int test10(Int2 i2) { return i2; }
|
||||
%}
|
||||
|
||||
%apply Int3 OKAY {Int3 i3} // applies (B) as 'Int3 OKAY' resolves to 'Int1 OKAY'
|
||||
%inline %{
|
||||
int test20(Int3 i3) { return i3; }
|
||||
%}
|
||||
|
||||
%typemap(in) int EXACT "_this_too_will_not_compile_"
|
||||
%typemap(in) Int1 EXACT "_this_too_will_not_compile_"
|
||||
%typemap(in) Int2 EXACT "_this_too_will_not_compile_"
|
||||
%typemap(in) Int3 EXACT "$1 = 30;"
|
||||
%apply Int3 EXACT {Int3 i3}
|
||||
|
||||
%inline %{
|
||||
int test30(Int3 i3) { return i3; }
|
||||
%}
|
||||
|
||||
|
||||
%typemap(in) int CONFUSING "_this_too_will_not_compile_"
|
||||
%typemap(in) int ii "$1 = 40;" // (D)
|
||||
%typemap(in) Int1 CONFUSING "_this_too_will_not_compile_"
|
||||
%typemap(in) Int2 CONFUSING "_this_too_will_not_compile_"
|
||||
%typemap(check) Int3 CONFUSING "/*check typemap*/"
|
||||
%apply Int3 CONFUSING {Int3 ii} // Only applies the (check) typemap above, the other CONFUSING typemaps are not applied as the repeated typedef lookups halts as soon as any typemap method matches
|
||||
|
||||
%inline %{
|
||||
int test40(Int3 ii) { return ii; } // Uses (D) using normal typemap lookup rules as the %apply above does not provide an 'in' typemap method in the family of 'Int3 CONFUSING' typemaps
|
||||
%}
|
||||
|
|
@ -125,6 +125,7 @@ CPP_TEST_CASES += \
|
|||
anonymous_bitfield \
|
||||
apply_signed_char \
|
||||
apply_strings \
|
||||
apply_typemap_typedefs \
|
||||
argcargvtest \
|
||||
argout \
|
||||
array_member \
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
from apply_typemap_typedefs import *
|
||||
|
||||
if test10(10) != 10:
|
||||
raise RuntimeError
|
||||
if test20(20) != 20:
|
||||
raise RuntimeError
|
||||
if test30(30) != 30:
|
||||
raise RuntimeError
|
||||
if test40(40) != 40:
|
||||
raise RuntimeError
|
|
@ -494,20 +494,23 @@ int Swig_typemap_apply(ParmList *src, ParmList *dest) {
|
|||
/* See if there is a matching typemap in this scope */
|
||||
sm = typemap_get(type, name);
|
||||
|
||||
/* if there is not matching, look for a typemap in the
|
||||
original typedef, if any, like in:
|
||||
/* If there is no exact match on the type, look for a typemap by resolving the type
|
||||
until/if a suitable match on the type is found, such as
|
||||
|
||||
typedef unsigned long size_t;
|
||||
...
|
||||
%apply(size_t) {my_size}; ==> %apply(unsigned long) {my_size};
|
||||
*/
|
||||
if (!sm) {
|
||||
SwigType *ntype = SwigType_typedef_resolve(type);
|
||||
if (ntype && (Cmp(ntype, type) != 0)) {
|
||||
SwigType *ntype = Copy(type);
|
||||
while (!sm && ntype) {
|
||||
SwigType *nt = ntype;
|
||||
ntype = SwigType_typedef_resolve(ntype);
|
||||
if (ntype) {
|
||||
sm = typemap_get(ntype, name);
|
||||
}
|
||||
Delete(ntype);
|
||||
Delete(nt);
|
||||
}
|
||||
Delete(ntype);
|
||||
|
||||
if (sm) {
|
||||
/* Got a typemap. Need to only merge attributes for methods that match our signature */
|
||||
|
|
Loading…
Reference in New Issue