Fix %newobject when used in conjunction with %feature(ref). The code from the ref feature was not always being generated for the function specified by %newobject. Documentation for ref and unref moved from Python to the C++ chapter.
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@12783 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
parent
86e1051a8b
commit
c794d08597
8 changed files with 262 additions and 160 deletions
|
|
@ -5,6 +5,11 @@ See the RELEASENOTES file for a summary of changes in each release.
|
||||||
Version 2.0.5 (in progress)
|
Version 2.0.5 (in progress)
|
||||||
===========================
|
===========================
|
||||||
|
|
||||||
|
2011-08-23: wsfulton
|
||||||
|
Fix %newobject when used in conjunction with %feature("ref") as reported by Jan Becker. The
|
||||||
|
code from the "ref" feature was not always being generated for the function specified by %newobject.
|
||||||
|
Documentation for "ref" and "unref" moved from Python to the C++ chapter.
|
||||||
|
|
||||||
2011-08-22: szager
|
2011-08-22: szager
|
||||||
[python] Fixed memory leak with --builtin option (bug 3385089).
|
[python] Fixed memory leak with --builtin option (bug 3385089).
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -704,6 +704,11 @@ depends on the target language on implementing the 'disown' mechanism
|
||||||
properly.
|
properly.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The use of <tt>%newobject</tt> is also integrated with reference counting and is covered in the
|
||||||
|
<a href="SWIGPlus.html#SWIGPlus_ref_unref">C++ reference counted objects</a> section.
|
||||||
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<b>Compatibility note:</b> Previous versions of SWIG had a special <tt>%new</tt> directive. However, unlike <tt>%newobject</tt>,
|
<b>Compatibility note:</b> Previous versions of SWIG had a special <tt>%new</tt> directive. However, unlike <tt>%newobject</tt>,
|
||||||
it only applied to the next declaration. For example:
|
it only applied to the next declaration. For example:
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@
|
||||||
<li><a href="#Python_nn25">C++ namespaces</a>
|
<li><a href="#Python_nn25">C++ namespaces</a>
|
||||||
<li><a href="#Python_nn26">C++ templates</a>
|
<li><a href="#Python_nn26">C++ templates</a>
|
||||||
<li><a href="#Python_nn27">C++ Smart Pointers</a>
|
<li><a href="#Python_nn27">C++ Smart Pointers</a>
|
||||||
<li><a href="#Python_nn27a">C++ Reference Counted Objects (ref/unref)</a>
|
<li><a href="#Python_nn27a">C++ reference counted objects</a>
|
||||||
</ul>
|
</ul>
|
||||||
<li><a href="#Python_nn28">Further details on the Python class interface</a>
|
<li><a href="#Python_nn28">Further details on the Python class interface</a>
|
||||||
<ul>
|
<ul>
|
||||||
|
|
@ -2053,147 +2053,11 @@ simply use the <tt>__deref__()</tt> method. For example:
|
||||||
</pre>
|
</pre>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<H3><a name="Python_nn27a"></a>33.3.15 C++ reference counted objects</H3>
|
||||||
<H3><a name="Python_nn27a"></a>33.3.15 C++ Reference Counted Objects (ref/unref)</H3>
|
|
||||||
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Another usual idiom in C++ is the use of reference counted
|
The <a href="SWIGPlus.html#SWIGPlus_ref_unref">C++ reference counted objects</a> section contains
|
||||||
objects. Consider for example:
|
Python examples of memory management using referencing counting.
|
||||||
|
|
||||||
<div class="code">
|
|
||||||
<pre>
|
|
||||||
class RCObj {
|
|
||||||
// implement the ref counting mechanism
|
|
||||||
int add_ref();
|
|
||||||
int del_ref();
|
|
||||||
int ref_count();
|
|
||||||
|
|
||||||
public:
|
|
||||||
virtual ~RCObj() = 0;
|
|
||||||
|
|
||||||
int ref() const {
|
|
||||||
return add_ref();
|
|
||||||
}
|
|
||||||
|
|
||||||
int unref() const {
|
|
||||||
if (ref_count() == 0 || del_ref() == 0 ) {
|
|
||||||
delete this;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return ref_count();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class A : RCObj {
|
|
||||||
public:
|
|
||||||
A();
|
|
||||||
int foo();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class B {
|
|
||||||
A *_a;
|
|
||||||
|
|
||||||
public:
|
|
||||||
B(A *a) : _a(a) {
|
|
||||||
a->ref();
|
|
||||||
}
|
|
||||||
|
|
||||||
~B() {
|
|
||||||
a->unref();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
A *a = new A();
|
|
||||||
a->ref(); // 'a' is ref here
|
|
||||||
|
|
||||||
B *b1 = new B(a); // 'a' is ref here
|
|
||||||
if (1 + 1 == 2) {
|
|
||||||
B *b2 = new B(a); // 'a' is ref here
|
|
||||||
delete b2; // 'a' is unref, but not deleted
|
|
||||||
}
|
|
||||||
|
|
||||||
delete b1; // 'a' is unref, but not deleted
|
|
||||||
a->unref(); // 'a' is unref and deleted
|
|
||||||
}
|
|
||||||
</pre>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
In the example above, the 'A' class instance 'a' is a reference counted
|
|
||||||
object, which can't be deleted arbitrarily since it is shared between
|
|
||||||
the objects 'b1' and 'b2'. 'A' is derived from an Reference Counted
|
|
||||||
Object 'RCObj', which implements the ref/unref idiom.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
To tell SWIG that 'RCObj' and all its derived classes are reference
|
|
||||||
counted objects, you use the "ref" and "unref" features.
|
|
||||||
For example:
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="code">
|
|
||||||
<pre>
|
|
||||||
%module example
|
|
||||||
...
|
|
||||||
|
|
||||||
%feature("ref") RCObj "$this->ref();"
|
|
||||||
%feature("unref") RCObj "$this->unref();"
|
|
||||||
|
|
||||||
%include "rcobj.h"
|
|
||||||
%include "A.h"
|
|
||||||
...
|
|
||||||
</pre>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
where the code passed to the "ref" and "unref" features will be
|
|
||||||
executed as needed whenever a new object is passed to python, or when
|
|
||||||
python tries to release the proxy object instance, respectively.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
In the python side, the use of a reference counted object is not
|
|
||||||
different than any other regular instance:
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div class="targetlang">
|
|
||||||
<pre>
|
|
||||||
def create_A():
|
|
||||||
a = A() # SWIG ref 'a' (new object is passed to python)
|
|
||||||
b1 = B(a) # C++ ref 'a'
|
|
||||||
if 1 + 1 == 2:
|
|
||||||
b2 = B(a) # C++ ref 'a'
|
|
||||||
return a # 'b1' and 'b2' are released, C++ unref 'a' twice
|
|
||||||
|
|
||||||
a = create_A()
|
|
||||||
exit # 'a' is released, SWIG unref 'a'
|
|
||||||
</pre>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Note that the user doesn't explicitly need to call 'a->ref()' nor 'a->unref()'
|
|
||||||
(as neither 'delete a'). Instead, SWIG take cares of executing the "ref"
|
|
||||||
and "unref" codes as needed. If the user doesn't specify the
|
|
||||||
"ref/unref" features, SWIG will produce a code equivalent to define
|
|
||||||
them as:
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div class="code">
|
|
||||||
<pre>
|
|
||||||
%feature("ref") ""
|
|
||||||
%feature("unref") "delete $this;"
|
|
||||||
</pre>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
In other words, SWIG will not do anything special when a new object
|
|
||||||
is passed to python, and it will always 'delete' the object when
|
|
||||||
python releases the proxy instance.
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4618,6 +4618,180 @@ p = f.__deref__() # Raw pointer from operator->
|
||||||
<b>Note:</b> Smart pointer support was first added in SWIG-1.3.14.
|
<b>Note:</b> Smart pointer support was first added in SWIG-1.3.14.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<H2><a name="SWIGPlus_ref_unref"></a>C++ reference counted objects - ref/unref feature</H2>
|
||||||
|
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Another similar idiom in C++ is the use of reference counted objects. Consider for example:
|
||||||
|
|
||||||
|
<div class="code">
|
||||||
|
<pre>
|
||||||
|
class RCObj {
|
||||||
|
// implement the ref counting mechanism
|
||||||
|
int add_ref();
|
||||||
|
int del_ref();
|
||||||
|
int ref_count();
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual ~RCObj() = 0;
|
||||||
|
|
||||||
|
int ref() const {
|
||||||
|
return add_ref();
|
||||||
|
}
|
||||||
|
|
||||||
|
int unref() const {
|
||||||
|
if (ref_count() == 0 || del_ref() == 0 ) {
|
||||||
|
delete this;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return ref_count();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class A : RCObj {
|
||||||
|
public:
|
||||||
|
A();
|
||||||
|
int foo();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class B {
|
||||||
|
A *_a;
|
||||||
|
|
||||||
|
public:
|
||||||
|
B(A *a) : _a(a) {
|
||||||
|
a->ref();
|
||||||
|
}
|
||||||
|
|
||||||
|
~B() {
|
||||||
|
a->unref();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
A *a = new A(); // (count: 0)
|
||||||
|
a->ref(); // 'a' ref here (count: 1)
|
||||||
|
|
||||||
|
B *b1 = new B(a); // 'a' ref here (count: 2)
|
||||||
|
if (1 + 1 == 2) {
|
||||||
|
B *b2 = new B(a); // 'a' ref here (count: 3)
|
||||||
|
delete b2; // 'a' unref, but not deleted (count: 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
delete b1; // 'a' unref, but not deleted (count: 1)
|
||||||
|
a->unref(); // 'a' unref and deleted (count: 0)
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
In the example above, the 'A' class instance 'a' is a reference counted
|
||||||
|
object, which can't be deleted arbitrarily since it is shared between
|
||||||
|
the objects 'b1' and 'b2'. 'A' is derived from a <i>Reference Counted
|
||||||
|
Object</i> 'RCObj', which implements the ref/unref idiom.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
To tell SWIG that 'RCObj' and all its derived classes are reference
|
||||||
|
counted objects, use the "ref" and "unref" <a href="Customization.html#Customization_features">features</a>.
|
||||||
|
These are also available as <tt>%refobject</tt> and <tt>%unrefobject</tt>, respectively.
|
||||||
|
For example:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="code">
|
||||||
|
<pre>
|
||||||
|
%module example
|
||||||
|
...
|
||||||
|
|
||||||
|
%feature("ref") RCObj "$this->ref();"
|
||||||
|
%feature("unref") RCObj "$this->unref();"
|
||||||
|
|
||||||
|
%include "rcobj.h"
|
||||||
|
%include "A.h"
|
||||||
|
...
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
where the code passed to the "ref" and "unref" features will be
|
||||||
|
executed as needed whenever a new object is passed to python, or when
|
||||||
|
python tries to release the proxy object instance, respectively.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
On the python side, the use of a reference counted object is no
|
||||||
|
different to any other regular instance:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="targetlang">
|
||||||
|
<pre>
|
||||||
|
def create_A():
|
||||||
|
a = A() # SWIG ref 'a' - new object is passed to python (count: 1)
|
||||||
|
b1 = B(a) # C++ ref 'a (count: 2)
|
||||||
|
if 1 + 1 == 2:
|
||||||
|
b2 = B(a) # C++ ref 'a' (count: 3)
|
||||||
|
return a # 'b1' and 'b2' are released and deleted, C++ unref 'a' twice (count: 1)
|
||||||
|
|
||||||
|
a = create_A() # (count: 1)
|
||||||
|
exit # 'a' is released, SWIG unref 'a' called in the destructor wrapper (count: 0)
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Note that the user doesn't explicitly need to call 'a->ref()' nor 'a->unref()'
|
||||||
|
(and neither 'delete a'). Instead, SWIG takes cares of executing the "ref"
|
||||||
|
and "unref" calls as needed. If the user doesn't specify the
|
||||||
|
"ref/unref" feature for a type, SWIG will produce code equivalent to defining these
|
||||||
|
features:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="code">
|
||||||
|
<pre>
|
||||||
|
%feature("ref") ""
|
||||||
|
%feature("unref") "delete $this;"
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
In other words, SWIG will not do anything special when a new object
|
||||||
|
is passed to python, and it will always 'delete' the underlying object when
|
||||||
|
python releases the proxy instance.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The <a href="Customization.html#Customization_ownership">%newobject feature</a> is designed to indicate to
|
||||||
|
the target language that it should take ownership of the returned object.
|
||||||
|
When used in conjunction with a type that has the "ref" feature associated with it, it additionally emits the
|
||||||
|
code in the "ref" feature into the C++ wrapper.
|
||||||
|
Consider wrapping the following factory function in addition to the above:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="code">
|
||||||
|
<pre>
|
||||||
|
%newobject AFactory;
|
||||||
|
A *AFactory() {
|
||||||
|
return new A();
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The <tt>AFactory</tt> function now acts much like a call to the <tt>A</tt> constructor with respect to memory handling:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="targetlang">
|
||||||
|
<pre>
|
||||||
|
a = AFactory() # SWIG ref 'a' due to %newobject (count: 1)
|
||||||
|
exit # 'a' is released, SWIG unref 'a' called in the destructor wrapper (count: 0)
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<H2><a name="SWIGPlus_nn35"></a>6.25 Using declarations and inheritance</H2>
|
<H2><a name="SWIGPlus_nn35"></a>6.25 Using declarations and inheritance</H2>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,14 +10,14 @@ b2 = B.create(a)
|
||||||
|
|
||||||
|
|
||||||
if a.ref_count() != 3:
|
if a.ref_count() != 3:
|
||||||
print "This program will crash... now"
|
raise RuntimeError("Count = %d" % a.ref_count())
|
||||||
|
|
||||||
|
|
||||||
rca = b2.get_rca()
|
rca = b2.get_rca()
|
||||||
b3 = B.create(rca)
|
b3 = B.create(rca)
|
||||||
|
|
||||||
if a.ref_count() != 5:
|
if a.ref_count() != 5:
|
||||||
print "This program will crash... now"
|
raise RuntimeError("Count = %d" % a.ref_count())
|
||||||
|
|
||||||
|
|
||||||
v = vector_A(2)
|
v = vector_A(2)
|
||||||
|
|
@ -27,6 +27,35 @@ v[1] = a
|
||||||
x = v[0]
|
x = v[0]
|
||||||
del v
|
del v
|
||||||
|
|
||||||
|
if a.ref_count() != 6:
|
||||||
|
raise RuntimeError("Count = %d" % a.ref_count())
|
||||||
|
|
||||||
|
# Check %newobject
|
||||||
|
b4 = b2.cloner()
|
||||||
|
if b4.ref_count() != 1:
|
||||||
|
raise RuntimeError
|
||||||
|
|
||||||
|
b5 = global_create(a)
|
||||||
|
if b5.ref_count() != 1:
|
||||||
|
raise RuntimeError
|
||||||
|
|
||||||
|
b6 = Factory.create(a)
|
||||||
|
if b6.ref_count() != 1:
|
||||||
|
raise RuntimeError
|
||||||
|
|
||||||
|
b7 = Factory().create2(a)
|
||||||
|
if b7.ref_count() != 1:
|
||||||
|
raise RuntimeError
|
||||||
|
|
||||||
|
|
||||||
|
if a.ref_count() != 10:
|
||||||
|
raise RuntimeError("Count = %d" % a.ref_count())
|
||||||
|
|
||||||
|
del b4
|
||||||
|
del b5
|
||||||
|
del b6
|
||||||
|
del b7
|
||||||
|
|
||||||
|
if a.ref_count() != 6:
|
||||||
|
raise RuntimeError("Count = %d" % a.ref_count())
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,8 @@
|
||||||
%}
|
%}
|
||||||
|
|
||||||
//
|
//
|
||||||
// using the %refobject/%unrefobject directives you can active the
|
// using the %refobject/%unrefobject directives you can activate the
|
||||||
// ref. counting for RCObj and all its descendents at once
|
// reference counting for RCObj and all its descendents at once
|
||||||
//
|
//
|
||||||
|
|
||||||
%refobject RCObj "$this->addref();"
|
%refobject RCObj "$this->addref();"
|
||||||
|
|
@ -18,7 +18,10 @@
|
||||||
%include "refcount.h"
|
%include "refcount.h"
|
||||||
|
|
||||||
%newobject B::create(A* a);
|
%newobject B::create(A* a);
|
||||||
|
%newobject global_create(A* a);
|
||||||
%newobject B::cloner();
|
%newobject B::cloner();
|
||||||
|
%newobject Factory::create(A* a);
|
||||||
|
%newobject Factory::create2(A* a);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -94,6 +97,22 @@
|
||||||
RCPtr<A> _a;
|
RCPtr<A> _a;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class B* global_create(A* a)
|
||||||
|
{
|
||||||
|
return new B(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Factory {
|
||||||
|
static B* create(A* a)
|
||||||
|
{
|
||||||
|
return new B(a);
|
||||||
|
}
|
||||||
|
B* create2(A* a)
|
||||||
|
{
|
||||||
|
return new B(a);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
%}
|
%}
|
||||||
|
|
||||||
#if defined(SWIGPYTHON) || defined(SWIGOCTAVE)
|
#if defined(SWIGPYTHON) || defined(SWIGOCTAVE)
|
||||||
|
|
|
||||||
|
|
@ -546,7 +546,7 @@ String *Swig_cppconstructor_director_call(const_String_or_char_ptr name, ParmLis
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
* Swig_rflag_search()
|
* recursive_flag_search()
|
||||||
*
|
*
|
||||||
* This function searches for the class attribute 'attr' in the class
|
* This function searches for the class attribute 'attr' in the class
|
||||||
* 'n' or recursively in its bases.
|
* 'n' or recursively in its bases.
|
||||||
|
|
@ -567,7 +567,7 @@ String *Swig_cppconstructor_director_call(const_String_or_char_ptr name, ParmLis
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
/* #define SWIG_FAST_REC_SEARCH 1 */
|
/* #define SWIG_FAST_REC_SEARCH 1 */
|
||||||
String *Swig_rflag_search(Node *n, const String *attr, const String *noattr) {
|
static String *recursive_flag_search(Node *n, const String *attr, const String *noattr) {
|
||||||
String *f = 0;
|
String *f = 0;
|
||||||
n = Swig_methodclass(n);
|
n = Swig_methodclass(n);
|
||||||
if (GetFlag(n, noattr)) {
|
if (GetFlag(n, noattr)) {
|
||||||
|
|
@ -581,7 +581,7 @@ String *Swig_rflag_search(Node *n, const String *attr, const String *noattr) {
|
||||||
if (bl) {
|
if (bl) {
|
||||||
Iterator bi;
|
Iterator bi;
|
||||||
for (bi = First(bl); bi.item; bi = Next(bi)) {
|
for (bi = First(bl); bi.item; bi = Next(bi)) {
|
||||||
f = Swig_rflag_search(bi.item, attr, noattr);
|
f = recursive_flag_search(bi.item, attr, noattr);
|
||||||
if (f) {
|
if (f) {
|
||||||
#ifdef SWIG_FAST_REC_SEARCH
|
#ifdef SWIG_FAST_REC_SEARCH
|
||||||
SetFlagAttr(n, attr, f);
|
SetFlagAttr(n, attr, f);
|
||||||
|
|
@ -600,12 +600,11 @@ String *Swig_rflag_search(Node *n, const String *attr, const String *noattr) {
|
||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
* Swig_unref_call()
|
* Swig_unref_call()
|
||||||
*
|
*
|
||||||
* find the unref call, if any.
|
* Find the "feature:unref" call, if any.
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
String *Swig_unref_call(Node *n) {
|
String *Swig_unref_call(Node *n) {
|
||||||
Node *cn = Swig_methodclass(n);
|
String *unref = recursive_flag_search(n, "feature:unref", "feature:nounref");
|
||||||
String *unref = Swig_rflag_search(cn, "feature:unref", "feature:nounref");
|
|
||||||
if (unref) {
|
if (unref) {
|
||||||
String *pname = Swig_cparm_name(0, 0);
|
String *pname = Swig_cparm_name(0, 0);
|
||||||
unref = NewString(unref);
|
unref = NewString(unref);
|
||||||
|
|
@ -619,12 +618,11 @@ String *Swig_unref_call(Node *n) {
|
||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
* Swig_ref_call()
|
* Swig_ref_call()
|
||||||
*
|
*
|
||||||
* find the ref call, if any.
|
* Find the "feature:ref" call, if any.
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
String *Swig_ref_call(Node *n, const String *lname) {
|
String *Swig_ref_call(Node *n, const String *lname) {
|
||||||
Node *cn = Swig_methodclass(n);
|
String *ref = recursive_flag_search(n, "feature:ref", "feature:noref");
|
||||||
String *ref = Swig_rflag_search(cn, "feature:ref", "feature:noref");
|
|
||||||
if (ref) {
|
if (ref) {
|
||||||
ref = NewString(ref);
|
ref = NewString(ref);
|
||||||
Replaceall(ref, "$this", lname);
|
Replaceall(ref, "$this", lname);
|
||||||
|
|
@ -642,7 +640,8 @@ String *Swig_ref_call(Node *n, const String *lname) {
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
String *Swig_cdestructor_call(Node *n) {
|
String *Swig_cdestructor_call(Node *n) {
|
||||||
String *unref = Swig_unref_call(n);
|
Node *cn = Swig_methodclass(n);
|
||||||
|
String *unref = Swig_unref_call(cn);
|
||||||
|
|
||||||
if (unref) {
|
if (unref) {
|
||||||
return unref;
|
return unref;
|
||||||
|
|
@ -664,7 +663,8 @@ String *Swig_cdestructor_call(Node *n) {
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
String *Swig_cppdestructor_call(Node *n) {
|
String *Swig_cppdestructor_call(Node *n) {
|
||||||
String *unref = Swig_unref_call(n);
|
Node *cn = Swig_methodclass(n);
|
||||||
|
String *unref = Swig_unref_call(cn);
|
||||||
if (unref) {
|
if (unref) {
|
||||||
return unref;
|
return unref;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -1309,15 +1309,21 @@ static String *Swig_typemap_lookup_impl(const_String_or_char_ptr tmap_method, No
|
||||||
int optimal_substitution = 0;
|
int optimal_substitution = 0;
|
||||||
int num_substitutions = 0;
|
int num_substitutions = 0;
|
||||||
|
|
||||||
/* special case, we need to check for 'ref' call and set the default code 'sdef' */
|
|
||||||
if (node && Cmp(tmap_method, "newfree") == 0) {
|
|
||||||
sdef = Swig_ref_call(node, lname);
|
|
||||||
}
|
|
||||||
|
|
||||||
type = Getattr(node, "type");
|
type = Getattr(node, "type");
|
||||||
if (!type)
|
if (!type)
|
||||||
return sdef;
|
return sdef;
|
||||||
|
|
||||||
|
/* Special hook (hack!). Check for the 'ref' feature and add code it contains to any 'newfree' typemap code.
|
||||||
|
* We could choose to put this hook into a number of different typemaps, not necessarily 'newfree'...
|
||||||
|
* Rather confusingly 'newfree' is used to release memory and the 'ref' feature is used to add in memory references - yuck! */
|
||||||
|
if (node && Cmp(tmap_method, "newfree") == 0) {
|
||||||
|
String *base = SwigType_base(type);
|
||||||
|
Node *typenode = Swig_symbol_clookup(base, 0);
|
||||||
|
if (typenode)
|
||||||
|
sdef = Swig_ref_call(typenode, lname);
|
||||||
|
Delete(base);
|
||||||
|
}
|
||||||
|
|
||||||
pname = Getattr(node, "name");
|
pname = Getattr(node, "name");
|
||||||
|
|
||||||
if (pname && node && checkAttribute(node, "kind", "function")) {
|
if (pname && node && checkAttribute(node, "kind", "function")) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue