$self special variable for %extend

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@9530 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
William S Fulton 2006-11-08 00:54:28 +00:00
commit ca6b2bfa2b
8 changed files with 62 additions and 30 deletions

View file

@ -824,11 +824,11 @@ Now we extend it with some new code
<div class="code"><pre>%extend Complex {
const char *__str__() {
static char tmp[1024];
sprintf(tmp,"Complex(%g,%g)", self-&gt;re(),self-&gt;im());
sprintf(tmp,"Complex(%g,%g)", $self-&gt;re(),$self-&gt;im());
return tmp;
}
bool operator==(const Complex&amp; c)
{ return (self-&gt;re()==c.re() &amp;&amp; self-&gt;im()==c.im();}
{ return ($self-&gt;re()==c.re() &amp;&amp; $self-&gt;im()==c.im();}
};
</pre></div>
<p>
@ -846,7 +846,7 @@ true
true
</pre></div>
<p>
Extend works with both C and C++ code, on classes and structs. It does not modify the underlying object in any way---the extensions only show up in the Lua interface. The only item to take note of is the code has to use the 'self' instead of 'this', and that you cannot access protected/private members of the code (as you are not officially part of the class).
Extend works with both C and C++ code, on classes and structs. It does not modify the underlying object in any way---the extensions only show up in the Lua interface. The only item to take note of is the code has to use the '$self' instead of 'this', and that you cannot access protected/private members of the code (as you are not officially part of the class).
</p>
<H3><a name="Lua_nn20"></a>22.3.13 C++ templates</H3>

View file

@ -3101,7 +3101,7 @@ struct Vector {
%extend Vector {
char *__str__() {
static char tmp[1024];
sprintf(tmp,"Vector(%g,%g,%g)", self-&gt;x,self-&gt;y,self-&gt;z);
sprintf(tmp,"Vector(%g,%g,%g)", $self-&gt;x,$self-&gt;y,$self-&gt;z);
return tmp;
}
Vector(double x, double y, double z) {
@ -3138,9 +3138,9 @@ For example, if you wanted to overload a Python operator, you might do this:
%extend Vector {
Vector __add__(Vector *other) {
Vector v;
v.x = self-&gt;x + other-&gt;x;
v.y = self-&gt;y + other-&gt;y;
v.z = self-&gt;z + other-&gt;z;
v.x = $self-&gt;x + other-&gt;x;
v.y = $self-&gt;y + other-&gt;y;
v.z = $self-&gt;z + other-&gt;z;
return v;
}
};

View file

@ -989,7 +989,7 @@ $ <b>ruby -e 'puts $:.join("\n")'</b><br>/usr/local/lib/ruby/site_ruby/1.6 /usr/
to add a new method of the aliased name that calls the original function. For
example: </p>
<div class="code">
<pre>class MyArray {<br>public:<br> // Construct an empty array<br> MyArray();<br> <br> // Return the size of this array<br> size_t length() const;<br>};<br><br>%extend MyArray {<br> // MyArray#size is an alias for MyArray#length<br> size_t size() const {<br> return self-&gt;length();<br> }<br>}
<pre>class MyArray {<br>public:<br> // Construct an empty array<br> MyArray();<br> <br> // Return the size of this array<br> size_t length() const;<br>};<br><br>%extend MyArray {<br> // MyArray#size is an alias for MyArray#length<br> size_t size() const {<br> return $self-&gt;length();<br> }<br>}
</pre>
</div>
<p> A better solution is to use the <tt>%alias</tt> directive (unique to

View file

@ -2356,18 +2356,23 @@ You can make a <tt>Vector</tt> look a lot like a class by writing a SWIG interfa
return v;
}
~Vector() {
free(self);
free($self);
}
double magnitude() {
return sqrt(self-&gt;x*self-&gt;x+self-&gt;y*self-&gt;y+self-&gt;z*self-&gt;z);
return sqrt($self-&gt;x*$self-&gt;x+$self-&gt;y*$self-&gt;y+$self-&gt;z*$self-&gt;z);
}
void print() {
printf("Vector [%g, %g, %g]\n", self-&gt;x,self-&gt;y,self-&gt;z);
printf("Vector [%g, %g, %g]\n", $self-&gt;x,$self-&gt;y,$self-&gt;z);
}
};
</pre></div>
<p>
Note the usage of the <tt>$self</tt> special variable.
Its usage is identical to a C++ 'this' pointer and should be used whenever access to the struct instance is required.
</p>
<p>
Now, when used with proxy classes in Python, you can do things like
this :</p>

View file

@ -2734,7 +2734,7 @@ public:
%extend {
char *__str__() {
static char temp[256];
sprintf(temp,"[ %g, %g, %g ]", self-&gt;x,self-&gt;y,self-&gt;z);
sprintf(temp,"[ %g, %g, %g ]", $self-&gt;x,$self-&gt;y,$self-&gt;z);
return &amp;temp[0];
}
}
@ -2760,10 +2760,37 @@ command.
</pre></div>
<p>
The C++ 'this' pointer is often needed to access member variables, methods etc.
The <tt>$self</tt> special variable should be used wherever you could use 'this'.
The example above demonstrates this for accessing member variables.
The implicit 'this' pointer that is present in C++ methods is not present in <tt>%extend</tt> methods.
In order to access anything in the extended class or its base class, an explicit 'this' is required.
The following example shows how one could access base class members:
</p>
<div class="code"><pre>
struct Base {
virtual void method(int v) {
...
}
int value;
};
struct Derived : Base {
};
%extend Derived {
virtual void method(int v) {
$self-&gt;Base::method(v);
$self-&gt;value = v;
...
}
}
</pre></div>
<p>
The<tt> %extend</tt> directive follows all of the same conventions
as its use with C structures. Please refer to the <a href="SWIG.html#SWIG">SWIG Basics</a>
chapter for further details.
as its use with C structures. Please refer to the <a href="SWIG.html#SWIG_adding_member_functions">Adding member functions to C structures</a>
section for further details.
</p>
<p>
@ -3446,7 +3473,7 @@ It is also possible to separate these declarations from the template class. For
}
/* Make a copy */
T *__copy__() {
return new List&lt;T&gt;(*self);
return new List&lt;T&gt;(*$self);
}
};

View file

@ -1276,7 +1276,7 @@ int Language::staticmemberfunctionHandler(Node *n) {
if (!defaultargs && code) {
/* Hmmm. An added static member. We have to create a little wrapper for this */
Swig_add_extension_code(n, cname, parms, type, code, CPlusPlus);
Swig_add_extension_code(n, cname, parms, type, code, CPlusPlus, 0);
}
}

View file

@ -737,19 +737,21 @@ String *Swig_cmemberget_call(const String_or_char *name, SwigType *t, String_or_
}
/* -----------------------------------------------------------------------------
* Swig_extension_code()
* extension_code()
*
* Generates an extension function (a function defined in %extend)
*
* return_type function_name(parms) code
*
* ----------------------------------------------------------------------------- */
String *Swig_extension_code(const String *function_name, ParmList *parms, SwigType *return_type, const String *code, int cplusplus) {
static String *extension_code(const String *function_name, ParmList *parms, SwigType *return_type, const String *code, int cplusplus, const String *self) {
String *parms_str = cplusplus ? ParmList_str_defaultargs(parms) : ParmList_str(parms);
String *sig = NewStringf("%s(%s)", function_name, parms_str);
String *rt_sig = SwigType_str(return_type, sig);
String *body = NewStringf("SWIGINTERN %s", rt_sig);
Printv(body, code, "\n", NIL);
if (self)
Replaceall(body, "$self", self);
Delete(parms_str);
Delete(sig);
Delete(rt_sig);
@ -762,11 +764,11 @@ String *Swig_extension_code(const String *function_name, ParmList *parms, SwigTy
* Generates an extension function (a function defined in %extend) and
* adds it to the "wrap:code" attribute of a node
*
* See also Swig_extension_code()
* See also extension_code()
*
* ----------------------------------------------------------------------------- */
int Swig_add_extension_code(Node *n, const String *function_name, ParmList *parms, SwigType *return_type, const String *code, int cplusplus) {
String *body = Swig_extension_code(function_name, parms, return_type, code, cplusplus);
int Swig_add_extension_code(Node *n, const String *function_name, ParmList *parms, SwigType *return_type, const String *code, int cplusplus, const String *self) {
String *body = extension_code(function_name, parms, return_type, code, cplusplus, self);
Setattr(n, k_wrapcode, body);
Delete(body);
return SWIG_OK;
@ -790,8 +792,8 @@ int Swig_MethodToFunction(Node *n, String *classname, int flags, SwigType *direc
if (flags & CWRAP_SMART_POINTER) {
self = NewString("(*this)->");
}
/* If node is a member template expansion, we don't allow added code */
/* If node is a member template expansion, we don't allow added code */
if (Getattr(n, k_templatetype))
flags &= ~(CWRAP_EXTEND);
@ -908,8 +910,7 @@ int Swig_MethodToFunction(Node *n, String *classname, int flags, SwigType *direc
/* See if there is any code that we need to emit */
if (!defaultargs && code && !is_smart_pointer) {
Swig_add_extension_code(n, mangled, p, type, code, cparse_cplusplus);
Swig_add_extension_code(n, mangled, p, type, code, cparse_cplusplus, k_self);
}
if (is_smart_pointer) {
int i = 0;
@ -1057,7 +1058,7 @@ int Swig_ConstructorToFunction(Node *n, String *classname, String *none_comparis
/* See if there is any code that we need to emit */
if (!defaultargs && code) {
Swig_add_extension_code(n, mangled, parms, type, code, cparse_cplusplus);
Swig_add_extension_code(n, mangled, parms, type, code, cparse_cplusplus, k_self);
}
call = Swig_cfunction_call(mangled, parms);
@ -1170,7 +1171,7 @@ int Swig_DestructorToFunction(Node *n, String *classname, int cplus, int flags)
mangled = Swig_name_mangle(membername);
code = Getattr(n, k_code);
if (code) {
Swig_add_extension_code(n, mangled, p, type, code, cparse_cplusplus);
Swig_add_extension_code(n, mangled, p, type, code, cparse_cplusplus, k_self);
}
call = Swig_cfunction_call(mangled, p);
cres = NewStringf("%s;\n", call);
@ -1256,7 +1257,7 @@ int Swig_MembersetToFunction(Node *n, String *classname, int flags) {
String *cres;
String *code = Getattr(n, k_code);
if (code) {
Swig_add_extension_code(n, mangled, parms, void_type, code, cparse_cplusplus);
Swig_add_extension_code(n, mangled, parms, void_type, code, cparse_cplusplus, k_self);
}
call = Swig_cfunction_call(mangled, parms);
cres = NewStringf("%s;\n", call);
@ -1332,7 +1333,7 @@ int Swig_MembergetToFunction(Node *n, String *classname, int flags) {
String *code = Getattr(n, k_code);
if (code) {
Swig_add_extension_code(n, mangled, parms, ty, code, cparse_cplusplus);
Swig_add_extension_code(n, mangled, parms, ty, code, cparse_cplusplus, k_self);
}
call = Swig_cfunction_call(mangled, parms);
cres = Swig_cresult(ty, k_result, call);

View file

@ -489,8 +489,7 @@ extern "C" {
extern String *Swig_cmemberset_call(String_or_char *name, SwigType *type, String_or_char *self, int varcref);
extern String *Swig_cmemberget_call(const String_or_char *name, SwigType *t, String_or_char *self, int varcref);
extern String *Swig_extension_code(const String *function_name, ParmList *parms, SwigType *return_type, const String *code, int cplusplus);
extern int Swig_add_extension_code(Node *n, const String *function_name, ParmList *parms, SwigType *return_type, const String *code, int cplusplus);
extern int Swig_add_extension_code(Node *n, const String *function_name, ParmList *parms, SwigType *return_type, const String *code, int cplusplus, const String *self);
/* --- Transformations --- */