Add new feature "python:cdefaultargs"
Controls default argument code generation to obtain the default arguments from the C++ layer instead of the Python layer.
This commit is contained in:
parent
986a13f1a0
commit
b8e1a66a38
5 changed files with 153 additions and 3 deletions
|
|
@ -5,7 +5,41 @@ See the RELEASENOTES file for a summary of changes in each release.
|
|||
Version 3.0.6 (in progress)
|
||||
===========================
|
||||
|
||||
2015-05-07: wsfulton
|
||||
2015-05-28: wsfulton
|
||||
[Python] Add new feature "python:cdefaultargs" to control default argument
|
||||
code generation. By default, SWIG attempts to convert C/C++ default argument values
|
||||
into Python values and generates code into the Python layer with these values.
|
||||
Recent versions of SWIG are able to convert more of these values, however, the
|
||||
new behaviour can be circumvented if desired via this new feature, such that
|
||||
the default argument values are obtained from the C layer and not the Python layer.
|
||||
For example:
|
||||
|
||||
struct CDA {
|
||||
int fff(int a = 1, bool b = false);
|
||||
};
|
||||
|
||||
The default code generation in the Python layer is:
|
||||
|
||||
class CDA(_object):
|
||||
...
|
||||
def fff(self, a=1, b=False):
|
||||
return _default_args.CDA_fff(self, a, b)
|
||||
|
||||
Adding the feature:
|
||||
|
||||
%feature("python:cdefaultargs") CDA::fff;
|
||||
|
||||
Results in:
|
||||
|
||||
class CDA(_object):
|
||||
...
|
||||
def fff(self, *args):
|
||||
return _default_args.CDA_fff(self, *args)
|
||||
|
||||
Some code generation modes, eg -builtin and -fastproxy, are unaffected by this as
|
||||
the default values are always obtained from the C layer.
|
||||
|
||||
2015-05-27: wsfulton
|
||||
[Python] Deal with an integer as the default value of a typedef to bool
|
||||
parameter in the C++ prototype. See #327. Regression from 3.0.0 onwards.
|
||||
|
||||
|
|
|
|||
|
|
@ -4147,6 +4147,105 @@ If you need to return binary data, you might use the
|
|||
also be used to extra binary data from arbitrary pointers.
|
||||
</p>
|
||||
|
||||
|
||||
<H3><a name="Python_default_args"></a>Default arguments</H3>
|
||||
|
||||
<p>
|
||||
C++ default argument code generation is documented in the main
|
||||
<a href="SWIG.html#SWIGPlus_default_args">Default arguments</a> section.
|
||||
There is also an optional Python specific feature that can be used called the <tt>python:cdefaultargs</tt>
|
||||
<a href="Customization.html#Customization_feature_flags">feature flag</a>.
|
||||
By default, SWIG attempts to convert C++ default argument values
|
||||
into Python values and generates code into the Python layer containing these values.
|
||||
For example:
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
struct CDA {
|
||||
int fff(int a = 1, bool b = false);
|
||||
};
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
From Python this can be called as follows:
|
||||
</p>
|
||||
|
||||
<div class="targetlang">
|
||||
<pre>
|
||||
>>> CDA().fff() # C++ layer receives a=1 and b=false
|
||||
>>> CDA().fff(2) # C++ layer receives a=2 and b=false
|
||||
>>> CDA().fff(3, True) # C++ layer receives a=3 and b=true
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
The default code generation in the Python layer is:
|
||||
</p>
|
||||
|
||||
<div class="targetlang">
|
||||
<pre>
|
||||
class CDA(object):
|
||||
...
|
||||
def fff(self, a=1, b=False):
|
||||
return _default_args.CDA_fff(self, a, b)
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
Adding the feature:
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
%feature("python:cdefaultargs") CDA::fff;
|
||||
struct CDA {
|
||||
int fff(int a = 1, bool b = false);
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
results in identical behaviour when called from Python, however, it results in different code generation:
|
||||
</p>
|
||||
|
||||
<div class="targetlang">
|
||||
<pre>
|
||||
class CDA(object):
|
||||
...
|
||||
def fff(self, *args):
|
||||
return _default_args.CDA_fff(self, *args)
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
The default arguments are obtained in the C++ wrapper layer instead of the Python layer.
|
||||
Some code generation modes are quite different, eg <tt>-builtin</tt> and <tt>-fastproxy</tt>,
|
||||
and are unaffected by <tt>python:cdefaultargs</tt> as the default values are always obtained from the C++ layer.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Note that not all default arguments can be converted into a Python equivalent.
|
||||
When SWIG does not convert them, it will generate code to obtain them from the C++ layer as if
|
||||
<tt>python:cdefaultargs</tt> was specified.
|
||||
This will happen if just one argument cannot be converted into a Python equivalent.
|
||||
This occurs typically when the argument is not fully numeric, such as <tt>int(1)</tt>:
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
struct CDA {
|
||||
int fff(int a = int(1), bool b = false);
|
||||
};
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
<b>Compatibility Note:</b> SWIG-3.0.6 introduced the <tt>python:cdefaultargs</tt> feature.
|
||||
Versions of SWIG prior to this varied in their ability to convert C++ default values into
|
||||
equivalent Python default argument values.
|
||||
</p>
|
||||
|
||||
<H2><a name="Python_nn53"></a>36.8 Typemaps</H2>
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -292,3 +292,12 @@ struct ConstMethods {
|
|||
inline int slightly_off_square(int square_error, int def17) { return def17*def17 + square_error; }
|
||||
%}
|
||||
|
||||
// Python C default args
|
||||
%feature("python:cdefaultargs") CDA::cdefaultargs_test1;
|
||||
%inline %{
|
||||
struct CDA {
|
||||
int cdefaultargs_test1(int a = 1) { return a; }
|
||||
int cdefaultargs_test2(int a = 1) { return a; }
|
||||
};
|
||||
%}
|
||||
|
||||
|
|
|
|||
|
|
@ -128,6 +128,13 @@ def run(module_name):
|
|||
if default_args.slightly_off_square() != 291:
|
||||
raise RuntimeError
|
||||
|
||||
# It is difficult to test the python:cdefaultargs feature properly as -builtin
|
||||
# and -fastproxy do not use the Python layer for default args
|
||||
if default_args.CDA().cdefaultargs_test1() != 1:
|
||||
raise RuntimeError
|
||||
|
||||
if default_args.CDA().cdefaultargs_test2() != 1:
|
||||
raise RuntimeError
|
||||
|
||||
if __name__ == "__main__":
|
||||
run('default_args')
|
||||
|
|
|
|||
|
|
@ -2082,9 +2082,10 @@ public:
|
|||
|
||||
1. The function is overloaded as Python doesn't support this.
|
||||
2. We were explicitly asked to use the "compact" arguments form.
|
||||
3. One of the default argument values can't be represented in Python.
|
||||
3. We were explicitly asked to use default args from C via the "python:cdefaultargs" feature.
|
||||
4. One of the default argument values can't be represented in Python.
|
||||
*/
|
||||
if (is_real_overloaded(n) || GetFlag(n, "feature:compactdefaultargs") || !is_representable_as_pyargs(n)) {
|
||||
if (is_real_overloaded(n) || GetFlag(n, "feature:compactdefaultargs") || GetFlag(n, "feature:python:cdefaultargs") || !is_representable_as_pyargs(n)) {
|
||||
String *parms = NewString("");
|
||||
if (in_class)
|
||||
Printf(parms, "self, ");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue