Add the optimal attribute to the out typemap for more optimal code generation when returning objects by value

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@10450 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
William S Fulton 2008-05-14 22:12:31 +00:00
commit 336b50b43d
39 changed files with 728 additions and 835 deletions

View file

@ -1,6 +1,12 @@
Version 1.3.36 (in progress)
=============================
05/14/2008: wsfulton
Add an optimisation for functions that return objects by value, reducing
the number of copies of the object that are made. Implemented using an
optional attribute in the "out" typemap called "optimal". Details in
Typemaps.html.
05/11/2008: olly
[PHP] Check for %feature("notabstract") when generating PHP5 class
wrapper.

View file

@ -379,6 +379,7 @@
<li><a href="Typemaps.html#Typemaps_nn41">Implementing constraints with typemaps</a>
</ul>
<li><a href="Typemaps.html#Typemaps_nn43">Typemaps for multiple languages</a>
<li><a href="Typemaps.html#Typemaps_optimal">Optimal code generation when returning by value</a>
<li><a href="Typemaps.html#Typemaps_nn42">Multi-argument typemaps</a>
<li><a href="Typemaps.html#runtime_type_checker">The run-time type checker</a>
<ul>
@ -761,7 +762,7 @@
<li><a href="Java.html#typeunsafe_enums_classes">Type unsafe enum classes</a>
</ul>
</ul>
<li><a href="Java.html#java_directors">Cross language polymorphism using directors (experimental)</a>
<li><a href="Java.html#java_directors">Cross language polymorphism using directors</a>
<ul>
<li><a href="Java.html#java_enabling_directors">Enabling directors</a>
<li><a href="Java.html#java_directors_classes">Director classes</a>

View file

@ -64,6 +64,7 @@
<li><a href="#Typemaps_nn41">Implementing constraints with typemaps</a>
</ul>
<li><a href="#Typemaps_nn43">Typemaps for multiple languages</a>
<li><a href="#Typemaps_optimal">Optimal code generation when returning by value</a>
<li><a href="#Typemaps_nn42">Multi-argument typemaps</a>
<li><a href="#runtime_type_checker">The run-time type checker</a>
<ul>
@ -2006,6 +2007,10 @@ $symname - Name of function/method being wrapped
</pre>
</div>
<p>
The "out" typemap supports an optional attribute flag called "optimal". This is for code optimisation and is detailed in the <a href="#Typemaps_optimal">Optimal code generation when returning by value</a> section.
</p>
<H3><a name="Typemaps_nn29"></a>10.5.4 "arginit" typemap</H3>
@ -2619,7 +2624,194 @@ The example above also shows a common approach of issuing a warning for an as ye
<tt>%typemap(ruby,in) int "$1 = NUM2INT($input);"</tt>.
</p>
<H2><a name="Typemaps_nn42"></a>10.8 Multi-argument typemaps</H2>
<H2><a name="Typemaps_optimal"></a>10.8 Optimal code generation when returning by value</H2>
<p>
The "out" typemap is the main typemap for return types.
This typemap supports an optional attribute flag called "optimal", which is for reducing
temporary variables and the amount of generated code.
It only really makes a difference when returning objects by value and it cannot always be used,
as explained later on.
<p>
<p>
When a function returns an object by value, SWIG generates code that instantiates the default
type on the stack then assigns the value returned by the function call to it.
A copy of this object is then made on the heap and this is what is ultimately stored and
used from the target language.
This will be clearer considering an example.
Consider running the following code through SWIG:
</p>
<div class="code">
<pre>
%typemap(out) SWIGTYPE %{
$result = new $1_ltype((const $1_ltype &amp;)$1);
%}
%inline %{
#include <iostream>
using namespace std;
struct XX {
XX() { cout &lt;&lt; "XX()" &lt;&lt; endl; }
XX(int i) { cout &lt;&lt; "XX(" &lt;&lt; i &lt;&lt; ")" &lt;&lt; endl; }
XX(const XX &amp;other) { cout &lt;&lt; "XX(const XX &amp;)" &lt;&lt; endl; }
XX &amp; operator =(const XX &amp;other) { cout &lt;&lt; "operator=(const XX &amp;)" &lt;&lt; endl; return *this; }
~XX() { cout &lt;&lt; "~XX()" &lt;&lt; endl; }
static XX create() {
return XX(0);
}
};
%}
</pre>
</div>
<p>
The "out" typemap shown is the default typemap for C# when returning by objects by value.
When making a call to <tt>XX::create()</tt> from C#, the output is as follows:
</p>
<div class="targetlang">
<pre>
XX()
XX(0)
operator=(const XX &amp;)
~XX()
XX(const XX &amp;)
~XX()
~XX()
</pre>
</div>
<p>
Note that three objects are being created as well as an assignment.
Wouldn't it be great if the <tt>XX::create()</tt> method was the only time a constructor was called?
As the method returns by value, this is asking a lot and the code that SWIG generates by default
makes it impossible for the compiler to make this type of optimisation.
However, this is where the "optimal" attribute in the "out" typemap can help out.
If the typemap code is kept the same and just the "optimal" attribute specified like this:
</p>
<div class="code">
<pre>
%typemap(out, optimal="1") SWIGTYPE %{
$result = new $1_ltype((const $1_ltype &amp;)$1);
%}
</pre>
</div>
<p>
then when the code is run again, the output is simply:
</P>
<div class="targetlang">
<pre>
XX(0)
~XX()
</pre>
</div>
<p>
How the "optimal" attribute works is best explained using the generated code.
Without "optimal", the generated code is:
</p>
<div class="code">
<pre>
SWIGEXPORT void * SWIGSTDCALL CSharp_XX_create() {
void * jresult ;
XX result;
result = XX::create();
jresult = new XX((const XX &amp;)result);
return jresult;
}
</pre>
</div>
<p>
With the "optimal" attribute, the code is:
</p>
<div class="code">
<pre>
SWIGEXPORT void * SWIGSTDCALL CSharp_XX_create() {
void * jresult ;
jresult = new XX((const XX &amp;)XX::create());
return jresult;
}
</pre>
</div>
<p>
The major difference is the <tt>result</tt> temporary variable holding the value returned from <tt>XX::create()</tt> is no longer generated and instead the copy constructor call is made directly from
the value returned by <tt>XX::create()</tt>.
With modern compiler optimisations turned on, the copy is not actually done, in fact the object is never created
on the stack in <tt>XX::create()</tt> at all, it is simply created directly on the heap.
In the first instance, the <tt>$1</tt> special variable in the typemap is expanded into <tt>result</tt>.
In the second instance, <tt>$1</tt> is expanded into <tt>XX::create()</tt> and this is essentially
what the "optimal" attribute is telling SWIG to do.
</p>
<p>
This kind of optimisation is not turned on by default as it has a number of restrictions.
Firstly, some code cannot be condensed into a simple call for passing into the copy constructor.
One common occurrence is when <a href="Customization.html#exception">%exception</a> is used.
Consider adding the following <tt>%exception</tt> to the example:
</p>
<div class="code">
<pre>
%exception XX::create() %{
try {
$action
} catch(const std::exception &amp;e) {
cout &lt;&lt; e.what() &lt;&lt; endl;
}
%}
</pre>
</div>
<p>
SWIG can detect when the "optimal" attribute cannot be used and will ignore it and in this case will issue the following warning:
</p>
<div class="targetlang">
<pre>
example.i:28: Warning(474): Method XX::create() usage of the optimal attribute in the out
typemap at example.i:14 ignored as the following cannot be used to generate optimal code:
try {
result = XX::create();
} catch(const std::exception &amp;e) {
cout &lt;&lt; e.what() &lt;&lt; endl;
}
</pre>
</div>
<p>
It should be clear that the above code cannot be used as the argument to the copy constructor call, ie for the <tt>$1</tt> substitution.
<p>
<p>
Secondly, if the typemaps uses <tt>$1</tt> more than once, then multiple calls to the wrapped function
will be made. Obviously that is not very optimal.
In fact SWIG attempts to detect this and will issue a warning something like:
</p>
<div class="targetlang">
<pre>
example.i:21: Warning(475): Multiple calls to XX::create() might be generated due to
optimal attribute usage in the out typemap at example.i:7.
</pre>
</div>
<p>
However, it doesn't always get it right, for example when <tt>$1</tt> is within some commented out code.
</p>
<H2><a name="Typemaps_nn42"></a>10.9 Multi-argument typemaps</H2>
<p>
@ -2884,7 +3076,7 @@ when crossing languages you may need to worry about issues such as row-major vs.
ordering (and perform conversions if needed).
</p>
<H2><a name="runtime_type_checker"></a>10.9 The run-time type checker</H2>
<H2><a name="runtime_type_checker"></a>10.10 The run-time type checker</H2>
<p>
@ -2910,7 +3102,7 @@ language modules.</li>
<li>Modules can be unloaded from the type system.</li>
</ul>
<H3><a name="Typemaps_nn45"></a>10.9.1 Implementation</H3>
<H3><a name="Typemaps_nn45"></a>10.10.1 Implementation</H3>
<p>
@ -3096,7 +3288,7 @@ structures rather than creating new ones. These <tt>swig_module_info</tt>
structures are chained together in a circularly linked list.
</p>
<H3><a name="Typemaps_nn46"></a>10.9.2 Usage</H3>
<H3><a name="Typemaps_nn46"></a>10.10.2 Usage</H3>
<p>This section covers how to use these functions from typemaps. To learn how to
@ -3190,7 +3382,7 @@ probably just look at the output of SWIG to get a better sense for how types are
managed.
</p>
<H2><a name="Typemaps_overloading"></a>10.10 Typemaps and overloading</H2>
<H2><a name="Typemaps_overloading"></a>10.11 Typemaps and overloading</H2>
<p>
@ -3499,7 +3691,7 @@ Subsequent "in" typemaps would then perform more extensive type-checking.
</li>
</ul>
<H2><a name="Typemaps_nn48"></a>10.11 More about <tt>%apply</tt> and <tt>%clear</tt></H2>
<H2><a name="Typemaps_nn48"></a>10.12 More about <tt>%apply</tt> and <tt>%clear</tt></H2>
<p>
@ -3584,7 +3776,7 @@ example:
</pre>
</div>
<H2><a name="Typemaps_nn49"></a>10.12 Reducing wrapper code size</H2>
<H2><a name="Typemaps_nn49"></a>10.13 Reducing wrapper code size</H2>
<p>
@ -3665,7 +3857,7 @@ convert_float_array(PyObject *input, int size) {
</pre>
</div>
<H2><a name="Typemaps_nn47"></a>10.13 Passing data between typemaps</H2>
<H2><a name="Typemaps_nn47"></a>10.14 Passing data between typemaps</H2>
<p>
@ -3702,7 +3894,7 @@ sure that the typemaps sharing information have exactly the same types and names
</p>
<H2><a name="Typemaps_nn51"></a>10.14 Where to go for more information?</H2>
<H2><a name="Typemaps_nn51"></a>10.15 Where to go for more information?</H2>
<p>

View file

@ -482,8 +482,12 @@ example.i(4): Syntax error in input.
<li>469. No or improper directorin typemap defined for <em>type</em>
<li>470. Thread/reentrant unsafe wrapping, consider returning by value instead.
<li>471. Unable to use return type <em>type</em> in director method
<li>474. Method <em>method</em> usage of the optimal attribute in the out typemap at <em>file</em>:<em>line</em> ignored as the following cannot be used to generate optimal code: <em>code</em>
<li>475. Multiple calls to <em>method</em> might be generated due to optimal attribute usage in the out typemap at <em>file</em>:<em>line</em>.
</ul>
<H3><a name="Warnings_nn14"></a>14.9.5 Code generation (500-599)</H3>

View file

@ -137,12 +137,13 @@ SWIG_TYPECHECK_STRING_ARRAY 1140
%typemap(lispclass) double "cl:double-float";
%typemap(lispclass) char * "cl:string";
%typemap(out) void "";
%typemap(out) bool "$result = (int)$1;";
%typemap(out) char, unsigned char, signed char,
short, signed short, unsigned short,
int, signed int, unsigned int,
long, signed long, unsigned long,
float, double, long double, char *, void *, void,
float, double, long double, char *, void *,
enum SWIGTYPE, SWIGTYPE *,
SWIGTYPE[ANY], SWIGTYPE & "$result = $1;";
#ifdef __cplusplus

View file

@ -80,12 +80,13 @@
SWIGTYPE[ANY], SWIGTYPE & "$1 = $input;";
%typemap(in) SWIGTYPE "$1 = *$input;";
%typemap(out) void "";
%typemap(out) bool "$result = (int)$1;";
%typemap(out) char, unsigned char, signed char,
short, signed short, unsigned short,
int, signed int, unsigned int,
long, signed long, unsigned long,
float, double, long double, char *, void *, void,
float, double, long double, char *, void *
enum SWIGTYPE, SWIGTYPE *,
SWIGTYPE[ANY], SWIGTYPE & "$result = $1;";
#ifdef __cplusplus

View file

@ -330,7 +330,7 @@ SIMPLE_TYPEMAP(double, C_c_double, C_flonum, C_swig_is_number, (double), C_SIZEO
{
$&1_ltype resultptr;
C_word *known_space = C_alloc(C_SIZEOF_SWIG_POINTER);
resultptr = new $1_ltype(($1_ltype &) $1);
resultptr = new $1_ltype((const $1_ltype &) $1);
$result = SWIG_NewPointerObj(resultptr, $&1_descriptor, 1);
}
#else
@ -348,7 +348,7 @@ SIMPLE_TYPEMAP(double, C_c_double, C_flonum, C_swig_is_number, (double), C_SIZEO
{
$&1_ltype resultptr;
C_word *known_space = C_alloc(C_SIZEOF_SWIG_POINTER);
resultptr = new $1_ltype(($1_ltype&) $1);
resultptr = new $1_ltype((const $1_ltype&) $1);
$result = SWIG_NewPointerObj(resultptr, $&1_descriptor, 0);
}
#else

View file

@ -376,7 +376,7 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) {
%typemap(out) SWIGTYPE
#ifdef __cplusplus
%{ $result = new $1_ltype(($1_ltype &)$1); %}
%{ $result = new $1_ltype((const $1_ltype &)$1); %}
#else
{
$&1_ltype $1ptr = ($&1_ltype) malloc(sizeof($1_ltype));

View file

@ -119,7 +119,7 @@
#ifdef __cplusplus
{
$&1_ltype resultptr;
resultptr = new $1_ltype(($1_ltype &) $1);
resultptr = new $1_ltype((const $1_ltype &) $1);
$result = SWIG_NewPointerObj (resultptr, $&1_descriptor, 1);
}
#else
@ -135,7 +135,7 @@
#ifdef __cplusplus
{
$&1_ltype resultptr;
resultptr = new $1_ltype(($1_ltype&) $1);
resultptr = new $1_ltype((const $1_ltype&) $1);
$result = SWIG_NewPointerObj (resultptr, $&1_descriptor, 0);
}
#else

View file

@ -579,7 +579,7 @@
%typemap(out) SWIGTYPE
#ifdef __cplusplus
%{ *($&1_ltype*)&$result = new $1_ltype(($1_ltype &)$1); %}
%{ *($&1_ltype*)&$result = new $1_ltype((const $1_ltype &)$1); %}
#else
{
$&1_ltype $1ptr = ($&1_ltype) malloc(sizeof($1_ltype));

View file

@ -189,7 +189,7 @@ $1=&temp;%}
#ifdef __cplusplus
%typemap(out) SWIGTYPE
{
$&1_ltype resultptr = new $1_ltype(($1_ltype &) $1);
$&1_ltype resultptr = new $1_ltype((const $1_ltype &) $1);
SWIG_NewPointerObj(L,(void *) resultptr,$&1_descriptor,1); SWIG_arg++;
}
#else

View file

@ -455,7 +455,7 @@ $1 = &temp; %}
$1 = *argp; %}
%typemap(out) SWIGTYPE
#ifdef __cplusplus
%{*($&1_ltype*)&$result = new $1_ltype(($1_ltype &)$1); %}
%{*($&1_ltype*)&$result = new $1_ltype((const $1_ltype &)$1); %}
#else
{
$&1_ltype $1ptr = ($&1_ltype) malloc(sizeof($1_ltype));

View file

@ -76,7 +76,7 @@
%typemap(out) SWIGTYPE {
/* %typemap(out) SWIGTYPE */
$&1_ltype temp = new $ltype(($1_ltype &) $1);
$&1_ltype temp = new $ltype((const $1_ltype &) $1);
CAML_VALUE *fromval = caml_named_value("create_$ntype_from_ptr");
if( fromval ) {
$result = callback(*fromval,caml_val_ptr((void *)temp,$&1_descriptor));

View file

@ -211,7 +211,7 @@
%typemap(out) SWIGTYPE
#ifdef __cplusplus
{
$&1_ltype resultobj = new $1_ltype(($1_ltype &) $1);
$&1_ltype resultobj = new $1_ltype((const $1_ltype &) $1);
SWIG_SetPointerZval(return_value, (void *)resultobj, $&1_descriptor, 1);
}
#else

View file

@ -136,7 +136,7 @@ extern "C" {
#ifdef __cplusplus
{
$&1_ltype resultptr;
resultptr = new $1_ltype(($1_ltype &) $1);
resultptr = new $1_ltype((const $1_ltype &) $1);
push_object(SWIG_NewPointerObj((void *) resultptr, $&1_descriptor, 1));
}
#else

View file

@ -161,6 +161,8 @@
#define WARN_TYPEMAP_DIRECTOROUT_UNDEF 471
#define WARN_TYPEMAP_TYPECHECK_UNDEF 472
#define WARN_TYPEMAP_DIRECTOROUT_PTR 473
#define WARN_TYPEMAP_OUT_OPTIMAL_IGNORED 474
#define WARN_TYPEMAP_OUT_OPTIMAL_MULTIPLE 475
/* -- Fragments -- */
#define WARN_FRAGMENT_NOT_FOUND 490

View file

@ -2517,7 +2517,7 @@ int ALLEGROCL::emit_defun(Node *n, File *f_cl) {
int ALLEGROCL::functionWrapper(Node *n) {
ParmList *parms = CopyParmList(Getattr(n, "parms"));
Wrapper *wrap = NewWrapper();
Wrapper *f = NewWrapper();
String *raw_return_type = Swig_typemap_lookup_new("ctype", n, "", 0);
SwigType *return_type = Swig_cparse_type(raw_return_type);
@ -2528,18 +2528,18 @@ int ALLEGROCL::functionWrapper(Node *n) {
if (!is_void_return) {
String *lresult_init = NewStringf("= (%s)0", raw_return_type);
Wrapper_add_localv(wrap, "lresult",
Wrapper_add_localv(f, "lresult",
SwigType_lstr(SwigType_ltype(return_type), "lresult"),
lresult_init, NIL);
Delete(lresult_init);
}
// Emit all of the local variables for holding arguments.
emit_args(Getattr(n, "type"), parms, wrap);
emit_parameter_variables(parms, f);
// Attach the standard typemaps
Swig_typemap_attach_parms("ctype", parms, wrap);
Swig_typemap_attach_parms("lin", parms, wrap);
emit_attach_parmmaps(parms, wrap);
Swig_typemap_attach_parms("ctype", parms, f);
Swig_typemap_attach_parms("lin", parms, f);
emit_attach_parmmaps(parms, f);
String *mangled = mangle_name(n);
Node *overloaded = Getattr(n, "sym:overloaded");
@ -2562,7 +2562,7 @@ int ALLEGROCL::functionWrapper(Node *n) {
emit_buffered_defuns(n);
emit_dispatch_defun(n);
}
DelWrapper(wrap);
DelWrapper(f);
return SWIG_OK;
}
}
@ -2609,7 +2609,7 @@ int ALLEGROCL::functionWrapper(Node *n) {
// canThrow(n, "in", p);
Replaceall(parm_code, "$input", arg);
Setattr(p, "emit:input", arg);
Printf(wrap->code, "%s\n", parm_code);
Printf(f->code, "%s\n", parm_code);
p = Getattr(p, "tmap:in:next");
}
@ -2619,28 +2619,30 @@ int ALLEGROCL::functionWrapper(Node *n) {
// Emit the function definition
String *signature = SwigType_str(return_type, name_and_parms);
Printf(wrap->def, "EXPORT %s {", signature);
Printf(f->def, "EXPORT %s {", signature);
if (CPlusPlus)
Printf(wrap->code, " try {\n");
emit_action(n, wrap);
if (!is_void_return) {
String *result_convert = Swig_typemap_lookup_new("out", n, "result", 0);
Replaceall(result_convert, "$result", "lresult");
Printf(wrap->code, "%s\n", result_convert);
Printf(wrap->code, " return lresult;\n");
Delete(result_convert);
}
Printf(f->code, " try {\n");
String *actioncode = emit_action(n);
String *result_convert = Swig_typemap_lookup_out("out", n, "result", f, actioncode);
Replaceall(result_convert, "$result", "lresult");
Printf(f->code, "%s\n", result_convert);
Printf(f->code, " return lresult;\n");
Delete(result_convert);
emit_return_variable(n, Getattr(n, "type"), f);
if (CPlusPlus) {
Printf(wrap->code, " } catch (...) {\n");
Printf(f->code, " } catch (...) {\n");
if (!is_void_return)
Printf(wrap->code, " return (%s)0;\n", raw_return_type);
Printf(wrap->code, " }\n");
Printf(f->code, " return (%s)0;\n", raw_return_type);
Printf(f->code, " }\n");
}
Printf(wrap->code, "}\n");
Printf(f->code, "}\n");
/* print this when in C mode? make this a command-line arg? */
if (Generate_Wrapper)
Wrapper_print(wrap, f_cxx);
Wrapper_print(f, f_cxx);
String *f_buffer = NewString("");
@ -2656,7 +2658,7 @@ int ALLEGROCL::functionWrapper(Node *n) {
}
}
DelWrapper(wrap);
DelWrapper(f);
return SWIG_OK;
}

View file

@ -354,7 +354,7 @@ int CFFI::functionWrapper(Node *n) {
ParmList *parms = Getattr(n, "parms");
String *iname = Getattr(n, "sym:name");
Wrapper *wrap = NewWrapper();
Wrapper *f = NewWrapper();
String *raw_return_type = Swig_typemap_lookup_new("ctype", n, "", 0);
SwigType *return_type = Swig_cparse_type(raw_return_type);
@ -364,7 +364,7 @@ int CFFI::functionWrapper(Node *n) {
if (!is_void_return) {
String *lresult_init = NewStringf("lresult = (%s)0", raw_return_type);
Wrapper_add_localv(wrap, "lresult", raw_return_type, lresult_init, NIL);
Wrapper_add_localv(f, "lresult", raw_return_type, lresult_init, NIL);
Delete(lresult_init);
}
@ -373,7 +373,7 @@ int CFFI::functionWrapper(Node *n) {
overname = Getattr(n, "sym:overname");
} else {
if (!addSymbol(iname, n)) {
DelWrapper(wrap);
DelWrapper(f);
return SWIG_ERROR;
}
}
@ -385,11 +385,11 @@ int CFFI::functionWrapper(Node *n) {
Setattr(n, "wrap:name", wname);
// Emit all of the local variables for holding arguments.
emit_args(Getattr(n, "type"), parms, wrap);
emit_parameter_variables(parms, f);
// Attach the standard typemaps
Swig_typemap_attach_parms("ctype", parms, wrap);
emit_attach_parmmaps(parms, wrap);
Swig_typemap_attach_parms("ctype", parms, f);
emit_attach_parmmaps(parms, f);
int num_arguments = emit_num_arguments(parms);
String *name_and_parms = NewStringf("%s (", wname);
@ -426,7 +426,7 @@ int CFFI::functionWrapper(Node *n) {
{
Replaceall(parm_code, "$input", arg);
Setattr(p, "emit:input", arg);
Printf(wrap->code, "%s\n", parm_code);
Printf(f->code, "%s\n", parm_code);
p = Getattr(p, "tmap:in:next");
}
@ -436,25 +436,26 @@ int CFFI::functionWrapper(Node *n) {
// Emit the function definition
String *signature = SwigType_str(return_type, name_and_parms);
Printf(wrap->def, "EXPORT %s {", signature);
Printf(wrap->code, " try {\n");
emit_action(n, wrap);
if (!is_void_return) {
String *result_convert = Swig_typemap_lookup_new("out", n, "result", 0);
Replaceall(result_convert, "$result", "lresult");
Printf(wrap->code, "%s\n", result_convert);
Printf(wrap->code, " return lresult;\n");
Delete(result_convert);
}
Printf(f->def, "EXPORT %s {", signature);
Printf(f->code, " try {\n");
Printf(wrap->code, " } catch (...) {\n");
String *actioncode = emit_action(n);
String *result_convert = Swig_typemap_lookup_out("out", n, "result", f, actioncode);
Replaceall(result_convert, "$result", "lresult");
Printf(f->code, "%s\n", result_convert);
Printf(f->code, " return lresult;\n");
Delete(result_convert);
emit_return_variable(n, Getattr(n, "type"), f);
Printf(f->code, " } catch (...) {\n");
if (!is_void_return)
Printf(wrap->code, " return (%s)0;\n", raw_return_type);
Printf(wrap->code, " }\n");
Printf(wrap->code, "}\n");
Printf(f->code, " return (%s)0;\n", raw_return_type);
Printf(f->code, " }\n");
Printf(f->code, "}\n");
if (CPlusPlus)
Wrapper_print(wrap, f_cxx);
Wrapper_print(f, f_cxx);
if (CPlusPlus) {
emit_defun(n, wname);
@ -482,7 +483,7 @@ int CFFI::functionWrapper(Node *n) {
// }
Delete(wname);
DelWrapper(wrap);
DelWrapper(f);
return SWIG_OK;
}

View file

@ -368,7 +368,7 @@ int CHICKEN::functionWrapper(Node *n) {
Wrapper_add_local(f, "resultobj", "C_word resultobj");
/* Write code to extract function parameters. */
emit_args(d, l, f);
emit_parameter_variables(l, f);
/* Attach the standard typemaps */
emit_attach_parmmaps(l, f);
@ -501,11 +501,6 @@ int CHICKEN::functionWrapper(Node *n) {
}
}
Setattr(n, "wrap:name", wname);
/* Emit the function call */
emit_action(n, f);
/* Insert argument output code */
have_argout = 0;
for (p = l; p;) {
@ -514,7 +509,7 @@ int CHICKEN::functionWrapper(Node *n) {
if (!have_argout) {
have_argout = 1;
// Print initial argument output code
Printf(f->code, "SWIG_Chicken_SetupArgout\n");
Printf(argout, "SWIG_Chicken_SetupArgout\n");
}
Replaceall(tm, "$source", Getattr(p, "lname"));
@ -528,8 +523,13 @@ int CHICKEN::functionWrapper(Node *n) {
}
}
Setattr(n, "wrap:name", wname);
/* Emit the function call */
String *actioncode = emit_action(n);
/* Return the function value */
if ((tm = Swig_typemap_lookup_new("out", n, "result", 0))) {
if ((tm = Swig_typemap_lookup_out("out", n, "result", f, actioncode))) {
Replaceall(tm, "$source", "result");
Replaceall(tm, "$target", "resultobj");
Replaceall(tm, "$result", "resultobj");
@ -547,6 +547,7 @@ int CHICKEN::functionWrapper(Node *n) {
} else {
Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(d, 0), name);
}
emit_return_variable(n, d, f);
/* Insert the argumetn output code */
Printv(f->code, argout, NIL);
@ -731,7 +732,7 @@ int CHICKEN::variableWrapper(Node *n) {
Replaceall(tm, "$target", name);
Replaceall(tm, "$input", "value");
/* Printv(f->code, tm, "\n",NIL); */
emit_action_code(n, f, tm);
emit_action_code(n, f->code, tm);
} else {
Swig_warning(WARN_TYPEMAP_VARIN_UNDEF, input_file, line_number, "Unable to set variable of type %s.\n", SwigType_str(t, 0));
}
@ -753,7 +754,7 @@ int CHICKEN::variableWrapper(Node *n) {
Replaceall(tm, "$target", "resultobj");
Replaceall(tm, "$result", "resultobj");
/* Printf(f->code, "%s\n", tm); */
emit_action_code(n, f, tm);
emit_action_code(n, f->code, tm);
} else {
Swig_warning(WARN_TYPEMAP_VAROUT_UNDEF, input_file, line_number, "Unable to read variable of type %s\n", SwigType_str(t, 0));
}
@ -926,7 +927,7 @@ int CHICKEN::constantWrapper(Node *n) {
Replaceall(tm, "$target", "resultobj");
Replaceall(tm, "$result", "resultobj");
/* Printf(f->code, "%s\n", tm); */
emit_action_code(n, f, tm);
emit_action_code(n, f->code, tm);
} else {
Swig_warning(WARN_TYPEMAP_VAROUT_UNDEF, input_file, line_number, "Unable to read variable of type %s\n", SwigType_str(t, 0));
}

View file

@ -757,7 +757,7 @@ public:
Printv(f->def, " SWIGEXPORT ", c_return_type, " SWIGSTDCALL ", wname, "(", NIL);
// Emit all of the local variables for holding arguments.
emit_args(t, l, f);
emit_parameter_variables(l, f);
/* Attach the standard typemaps */
emit_attach_parmmaps(l, f);
@ -901,25 +901,26 @@ public:
}
}
if (Cmp(nodeType(n), "constant") == 0) {
// Wrapping a constant hack
Swig_save("functionWrapper", n, "wrap:action", NIL);
// below based on Swig_VargetToFunction()
SwigType *ty = Swig_wrapped_var_type(Getattr(n, "type"), use_naturalvar_mode(n));
Setattr(n, "wrap:action", NewStringf("result = (%s) %s;", SwigType_lstr(ty, 0), Getattr(n, "value")));
}
// Now write code to make the function call
if (!native_function_flag)
emit_action(n, f);
if (Cmp(nodeType(n), "constant") == 0)
Swig_restore(n);
/* Return value if necessary */
String *null_attribute = 0;
// Now write code to make the function call
if (!native_function_flag) {
if ((tm = Swig_typemap_lookup_new("out", n, "result", 0))) {
if (Cmp(nodeType(n), "constant") == 0) {
// Wrapping a constant hack
Swig_save("functionWrapper", n, "wrap:action", NIL);
// below based on Swig_VargetToFunction()
SwigType *ty = Swig_wrapped_var_type(Getattr(n, "type"), use_naturalvar_mode(n));
Setattr(n, "wrap:action", NewStringf("result = (%s) %s;", SwigType_lstr(ty, 0), Getattr(n, "value")));
}
Swig_director_emit_dynamic_cast(n, f);
String *actioncode = emit_action(n);
if (Cmp(nodeType(n), "constant") == 0)
Swig_restore(n);
/* Return value if necessary */
if ((tm = Swig_typemap_lookup_out("out", n, "result", f, actioncode))) {
canThrow(n, "out", n);
Replaceall(tm, "$source", "result"); /* deprecated */
Replaceall(tm, "$target", "jresult"); /* deprecated */
@ -937,6 +938,7 @@ public:
} else {
Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(t, 0), Getattr(n, "name"));
}
emit_return_variable(n, t, f);
}
/* Output argument output code */
@ -3463,9 +3465,6 @@ public:
// Get any Java exception classes in the throws typemap
ParmList *throw_parm_list = NULL;
if ((tm = Swig_typemap_lookup_new("out", n, "", 0)))
addThrows(n, "tmap:out", n);
if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) {
int gencomma = 0;
@ -3507,8 +3506,7 @@ public:
if (!is_void) {
Parm *tp = NewParmFromNode(returntype, empty_str, n);
tm = Swig_typemap_lookup_new("csdirectorout", tp, "", 0);
if (tm) {
if ((tm = Swig_typemap_lookup_new("csdirectorout", tp, "", 0))) {
substituteClassname(returntype, tm);
Replaceall(tm, "$cscall", upcall);

Some files were not shown because too many files have changed in this diff Show more