Add support for "ret" typemap where missing and improve documentation on it.

This commit is contained in:
William S Fulton 2016-09-29 08:06:22 +01:00
parent 7bfa5fb951
commit 08688d7d9d
11 changed files with 123 additions and 17 deletions

View File

@ -5,6 +5,11 @@ See the RELEASENOTES file for a summary of changes in each release.
Version 3.0.11 (in progress)
============================
2016-09-29: wsfulton
[Allegrocl, CFFI, GO, Javascript, Ocaml, R, Scilab]
Add missing support for the "ret" typemap in a few target languages.
The documentation also now has info on the "ret" typemap.
2016-09-27: ahmed-usman
[xml] Handle template parameters correctly.

View File

@ -457,6 +457,7 @@
<li><a href="Typemaps.html#Typemaps_nn32">"argout" typemap</a>
<li><a href="Typemaps.html#Typemaps_nn33">"freearg" typemap</a>
<li><a href="Typemaps.html#Typemaps_nn34">"newfree" typemap</a>
<li><a href="Typemaps.html#Typemaps_ret">"ret" typemap</a>
<li><a href="Typemaps.html#Typemaps_nn35">"memberin" typemap</a>
<li><a href="Typemaps.html#Typemaps_nn36">"varin" typemap</a>
<li><a href="Typemaps.html#Typemaps_nn37">"varout" typemap</a>

View File

@ -63,6 +63,7 @@
<li><a href="#Typemaps_nn32">"argout" typemap</a>
<li><a href="#Typemaps_nn33">"freearg" typemap</a>
<li><a href="#Typemaps_nn34">"newfree" typemap</a>
<li><a href="#Typemaps_ret">"ret" typemap</a>
<li><a href="#Typemaps_nn35">"memberin" typemap</a>
<li><a href="#Typemaps_nn36">"varin" typemap</a>
<li><a href="#Typemaps_nn37">"varout" typemap</a>
@ -2802,7 +2803,46 @@ string *foo();
See <a href="Customization.html#Customization_ownership">Object ownership and %newobject</a> for further details.
</p>
<H3><a name="Typemaps_nn35">11.5.10 "memberin" typemap</a></H3>
<H3><a name="Typemaps_ret">11.5.10 "ret" typemap</a></H3>
<p>
The "ret" typemap is not used very often, but can be useful for anything associated with
the return type, such as resource management, return value error checking, etc.
Usually this can all be done in the "out" typemap, but sometimes it is handy to use the
"out" typemap code untouched and add to the generated code using the code in the "ret" typemap.
One such case is memory clean up. For example, a <tt>stringheap_t</tt> type is defined indicating
that the returned memory must be deleted and a <tt>string_t</tt> type is defined indicating
that the returned memory must not be deleted.
</p>
<div class="code">
<pre>
%typemap(ret) stringheap_t %{
free($1);
%}
typedef char * string_t;
typedef char * stringheap_t;
string_t MakeString1();
stringheap_t MakeString2();
</pre>
</div>
<p>
The "ret" typemap above will only be used for <tt>MakeString2</tt>, but both functions
will use the default "out" typemap for <tt>char *</tt> provided by SWIG.
The code above would ensure the appropriate memory is freed in all target languages as the need
to provide custom "out" typemaps (which involve target language specific code) is not necessary.
</p>
<p>
This approach is an alternative to using the "newfree" typemap and <tt>%newobject</tt> as there
is no need to list all the functions that require the memory cleanup, it is purely done on types.
</p>
<H3><a name="Typemaps_nn35">11.5.11 "memberin" typemap</a></H3>
<p>
@ -2824,7 +2864,7 @@ It is rarely necessary to write "memberin" typemaps---SWIG already provides
a default implementation for arrays, strings, and other objects.
</p>
<H3><a name="Typemaps_nn36">11.5.11 "varin" typemap</a></H3>
<H3><a name="Typemaps_nn36">11.5.12 "varin" typemap</a></H3>
<p>
@ -2832,7 +2872,7 @@ The "varin" typemap is used to convert objects in the target language to C for t
purposes of assigning to a C/C++ global variable. This is implementation specific.
</p>
<H3><a name="Typemaps_nn37">11.5.12 "varout" typemap</a></H3>
<H3><a name="Typemaps_nn37">11.5.13 "varout" typemap</a></H3>
<p>
@ -2840,7 +2880,7 @@ The "varout" typemap is used to convert a C/C++ object to an object in the targe
language when reading a C/C++ global variable. This is implementation specific.
</p>
<H3><a name="throws_typemap">11.5.13 "throws" typemap</a></H3>
<H3><a name="throws_typemap">11.5.14 "throws" typemap</a></H3>
<p>

View File

@ -25,23 +25,33 @@ void foo1(Foo<int> f, const Foo<int>& ff) {}
void foo2(Foo<short> f, const Foo<short>& ff) {}
%}
#ifdef SWIGUTL
%typemap(ret) int Bar1::foo() { /* hello1 */ };
%typemap(ret) int Bar2::foo() { /* hello2 */ };
%typemap(ret) int foo() {/* hello3 */ };
#endif
// Check "ret" typemap is implemented
%{
template<typename T> struct NeededForTest {};
%}
%fragment("NeededForTest", "header") %{
template<> struct NeededForTest<short> { NeededForTest(short) {} };
%}
%typemap(ret) short "_ret_typemap_for_short_no_compile"
%typemap(ret, fragment="NeededForTest") short Bar1::foofunction() { /* ret typemap for short */ NeededForTest<short> needed($1); };
%typemap(ret, fragment="NeededForTest") short globalfoofunction() { /* ret typemap for short */ NeededForTest<short> needed($1); };
%inline %{
struct Bar1 {
int foo() { return 1;}
};
struct Bar2 {
int foo() { return 1;}
short foofunction() { return 1;}
};
short globalfoofunction() { return 1;}
%}
%{
void CheckRetTypemapUsed() {
// If the "ret" typemap is not used, the NeededForTest template specialization will not have been
// generated and so the following code will result in a compile failure
NeededForTest<short> needed(111);
(void)needed;
}
%}
%newobject FFoo::Bar(bool) const ;
%typemap(newfree) char* Bar(bool) {
@ -62,7 +72,7 @@ void foo2(Foo<short> f, const Foo<short>& ff) {}
#endif
// Test obscure bug where named typemaps where not being applied when symbol name contained a number
%typemap(out) double "_typemap_for_double_no_compile_"
%typemap(out) double "_out_typemap_for_double_no_compile_"
%typemap(out) double ABCD::meth {$1 = 0.0; TYPEMAP_OUT_INIT}
%typemap(out) double ABCD::m1 {$1 = 0.0; TYPEMAP_OUT_INIT}
%typemap(out) double ABCD::_x2 {$1 = 0.0; TYPEMAP_OUT_INIT}

View File

@ -2722,6 +2722,13 @@ int ALLEGROCL::functionWrapper(Node *n) {
}
}
/* See if there is any return cleanup code */
if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
Replaceall(tm, "$source", Swig_cresult_name());
Printf(f->code, "%s\n", tm);
Delete(tm);
}
emit_return_variable(n, t, f);
if (CPlusPlus) {

View File

@ -543,6 +543,14 @@ int CFFI::functionWrapper(Node *n) {
cleanupFunction(n, f, parms);
/* See if there is any return cleanup code */
String *tm = 0;
if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
Replaceall(tm, "$source", Swig_cresult_name());
Printf(f->code, "%s\n", tm);
Delete(tm);
}
if (!is_void_return) {
Printf(f->code, " return lresult;\n");
}

View File

@ -2599,6 +2599,14 @@ private:
Replaceall(f->code, "$cleanup", cleanup);
Delete(cleanup);
/* See if there is any return cleanup code */
String *tm;
if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
Replaceall(tm, "$source", Swig_cresult_name());
Printf(f->code, "%s\n", tm);
Delete(tm);
}
Replaceall(f->code, "$symname", Getattr(n, "sym:name"));
}

View File

@ -1354,6 +1354,11 @@ void JSEmitter::emitCleanupCode(Node *n, Wrapper *wrapper, ParmList *params) {
}
}
/* See if there is any return cleanup code */
if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
Printf(wrapper->code, "%s\n", tm);
Delete(tm);
}
}
int JSEmitter::switchNamespace(Node *n) {

View File

@ -676,6 +676,14 @@ public:
Printv(f->code, tm, "\n", NIL);
}
}
/* See if there is any return cleanup code */
if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
Replaceall(tm, "$source", Swig_cresult_name());
Printf(f->code, "%s\n", tm);
Delete(tm);
}
// Free any memory allocated by the function being wrapped..
if ((tm = Swig_typemap_lookup("swig_result", n, Swig_cresult_name(), 0))) {

View File

@ -2097,6 +2097,13 @@ int R::functionWrapper(Node *n) {
}
}
/* See if there is any return cleanup code */
if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
Replaceall(tm, "$source", Swig_cresult_name());
Printf(f->code, "%s\n", tm);
Delete(tm);
}
Printv(f->code, UnProtectWrapupCode, NIL);
/*If the user gave us something to convert the result in */

View File

@ -412,7 +412,7 @@ public:
emit_return_variable(node, functionReturnType, wrapper);
/* Return the function value if necessary */
String *functionReturnTypemap = Swig_typemap_lookup_out("out", node, "result", wrapper, functionActionCode);
String *functionReturnTypemap = Swig_typemap_lookup_out("out", node, Swig_cresult_name(), wrapper, functionActionCode);
if (functionReturnTypemap) {
// Result is actually the position of output value on stack
if (Len(functionReturnTypemap) > 0) {
@ -471,6 +471,13 @@ public:
}
}
/* See if there is any return cleanup code */
String *tm;
if ((tm = Swig_typemap_lookup("ret", node, Swig_cresult_name(), 0))) {
Replaceall(tm, "$source", Swig_cresult_name());
Printf(wrapper->code, "%s\n", tm);
Delete(tm);
}
/* Close the function(ok) */
Printv(wrapper->code, "return SWIG_OK;\n", NIL);