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:
parent
ed0e1c7d90
commit
336b50b43d
39 changed files with 728 additions and 835 deletions
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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 &)$1);
|
||||
%}
|
||||
|
||||
%inline %{
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
struct XX {
|
||||
XX() { cout << "XX()" << endl; }
|
||||
XX(int i) { cout << "XX(" << i << ")" << endl; }
|
||||
XX(const XX &other) { cout << "XX(const XX &)" << endl; }
|
||||
XX & operator =(const XX &other) { cout << "operator=(const XX &)" << endl; return *this; }
|
||||
~XX() { cout << "~XX()" << 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 &)
|
||||
~XX()
|
||||
XX(const XX &)
|
||||
~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 &)$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 &)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 &)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 &e) {
|
||||
cout << e.what() << 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 &e) {
|
||||
cout << e.what() << 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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Reference in a new issue