Fix a bug where chicken wrappers were not correctly registering values with the

chicken garbage collector.
Update the chicken documentation to reflect the new proxy class support.


git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@6648 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
John Lenz 2004-11-03 23:13:59 +00:00
commit bf83bb81a1
6 changed files with 72 additions and 221 deletions

View file

@ -18,7 +18,7 @@
<li><a href="#Chicken_nn5">Code Generation</a> <li><a href="#Chicken_nn5">Code Generation</a>
<ul> <ul>
<li><a href="#Chicken_nn6">Naming Conventions</a> <li><a href="#Chicken_nn6">Naming Conventions</a>
<li><a href="#Chicken_nn7">Modules and Prefixes</a> <li><a href="#Chicken_nn7">Modules</a>
<li><a href="#Chicken_nn8">Constants and Variables</a> <li><a href="#Chicken_nn8">Constants and Variables</a>
<li><a href="#Chicken_nn9">Functions</a> <li><a href="#Chicken_nn9">Functions</a>
</ul> </ul>
@ -31,7 +31,7 @@
</ul> </ul>
<li><a href="#Chicken_nn15">Typemaps</a> <li><a href="#Chicken_nn15">Typemaps</a>
<li><a href="#Chicken_nn16">Pointers</a> <li><a href="#Chicken_nn16">Pointers</a>
<li><a href="#Chicken_nn17">Unsupported features</a> <li><a href="#Chicken_nn17">Unsupported features and known problems</a>
</ul> </ul>
<!-- INDEX --> <!-- INDEX -->
@ -125,9 +125,8 @@
</blockquote> </blockquote>
<p> <p>
This will generate <tt>example_wrap.cxx</tt>, This will generate <tt>example_wrap.cxx</tt> and
<tt>example.scm</tt>, <tt>example-generic.scm</tt> and <tt>example.scm</tt>. The basic Scheme code must be
<tt>example-clos.scm</tt>. The basic Scheme code must be
compiled to C using your system's CHICKEN compiler. compiled to C using your system's CHICKEN compiler.
</p> </p>
@ -150,21 +149,10 @@
<p> <p>
Given a C variable, function or constant declaration named Given a C variable, function or constant declaration named
<tt>Foo_Bar_to_Foo_Baz</tt>, the declaration will be available <tt>Foo_Bar</tt>, the declaration will be available
in CHICKEN as an identifier ending with in CHICKEN as an identifier ending with
<tt>Foo-Bar-&gt;Foo-Baz</tt>. That is, an underscore is converted <tt>Foo-Bar</tt>. That is, an underscore is converted
to a dash and '_to_' is converted to an arrow. to a dash.
<br>
Additionally, there is a <em>mixed</em> mode that can be
specified with the <tt>-mixed</tt> option on the SWIG command
line. In this mode, the above rules apply with the addition
that changes in case are indications to SWIG CHICKEN to place a
dash in the CHICKEN identifier and the name is converted to lowercase.
For example, a C declartaion
named <tt>someDeclaration_xyz</tt> will be available as the
CHICKEN identifier ending with <tt>some-declaration-xyz</tt>.
<br> <br>
@ -172,41 +160,21 @@
<tt>%rename</tt> SWIG directive in the SWIG interface file. <tt>%rename</tt> SWIG directive in the SWIG interface file.
</p> </p>
<H3><a name="Chicken_nn7"></a>17.2.2 Modules and Prefixes</H3> <H3><a name="Chicken_nn7"></a>17.2.2 Modules</H3>
<p> The name of the module must be declared one of two ways:
SWIG CHICKEN does not use the standard CHICKEN module system
(which has been deprecated); instead, it uses a prefix system.
Specifying the module name as 'example' in SWIG CHICKEN can be
done using either of:
</p>
<ul> <ul>
<li>Placing <tt>%module example</tt> in the SWIG interface <li>Placing <tt>%module example</tt> in the SWIG interface
file.</li> file.</li>
<li>Using <tt>-module example</tt> on the SWIG command <li>Using <tt>-module example</tt> on the SWIG command
line.</li> line.</li>
</ul> </ul>
The generated example.scm file then exports <code>(declare (unit modulename))</code>
<p> <p>
CHICKEN will be able to access the module using the <tt>(declare CHICKEN will be able to access the module using the <code>(declare
(uses <i>modulename</i>))</tt> CHICKEN Scheme form. (uses <i>modulename</i>))</code> CHICKEN Scheme form.
<br>
Normally, for a C declaration <tt>Foo_Bar</tt> with a module
name of 'example', the corresponding CHICKEN identifier will be
<tt>example:Foo-Bar</tt>. <strong>The module name and a colon is
prefixed to the CHICKEN identifier</strong> (following normal
naming conventions).
<br>
You may explicitly override the prefix with the SWIG command
line option <tt>-prefix <i>whateverprefix</i></tt>, or you may
remove the prefix with the option <tt>-noprefix</tt>.
</p>
<H3><a name="Chicken_nn8"></a>17.2.3 Constants and Variables</H3> <H3><a name="Chicken_nn8"></a>17.2.3 Constants and Variables</H3>
@ -278,22 +246,24 @@
<p> <p>
CHICKEN has a modified version of TinyCLOS, which SWIG CHICKEN CHICKEN has a modified version of TinyCLOS, which SWIG CHICKEN
uses in C++ mode. SWIG CHICKEN generates a uses if the -proxy argument is given. If -proxy is passed, then
<tt>xxx-generic.scm</tt> and a <tt>xxx-clos.scm</tt> file, which the generated example.scm file will contain TinyCLOS class definitions.
contain TinyCLOS macros. When using these macros, you will need A class named Foo is declared as &lt;Foo&gt;, and each member variable
to <tt>(include "xxx-generic")</tt> all the generic macros your is allocated a slot. Member functions are exported as generic functions.
program needs, and <strong>then</strong> <tt>(include
"xxx-clos")</tt> all the metaobject (class) macros your program
needs.
</p>
<p> <p>
SWIG CHICKEN will call the destructor for all TinyCLOS objects Primitive symbols and functions (the interface that would be presented if
that are garbage-collected by CHICKEN. It also allows access to -proxy was not passed) are hidden and no longer accessable. If the -unhideprimitive
the underlying low-level Scheme procedures with (de)-marshaling command line argument is passed to SWIG, then the primitive symbols will be
of any TinyCLOS parameters. It is best to learn the TinyCLOS available, but each will be prefixed by the string "primitive:"
system by running the <tt>Examples/chicken/class/</tt> example.
<p>
The exported symbol names can be controlled with the -closprefix and -useclassprefix arguments.
If -useclassprefix is passed to SWIG, every member function will be generated with the class name
as a prefix. If the -closprefix mymod: argument is passed to SWIG, then the exported functions will
be prefixed by the string "mymod:". If -useclassprefix is passed, -closprefix is ignored.
</p> </p>
@ -347,6 +317,12 @@
when compiling example.scm, csc compiles that into example.c! when compiling example.scm, csc compiles that into example.c!
</p> </p>
<p>
The test_script.scm should have <code>(load-library 'example "example.so")</code>
and <code>(declare (uses example))</code>. As well, the path to example.so should
be accessable to the loader. You might need to set LD_LIBRARY_PATH.
</p>
<H3><a name="Chicken_nn14"></a>17.5.2 Static binary</H3> <H3><a name="Chicken_nn14"></a>17.5.2 Static binary</H3>
@ -369,139 +345,6 @@
<code>Lib/chicken/chicken.swg</code>. <code>Lib/chicken/chicken.swg</code>.
</p> </p>
<p>
Two Chicken-specific typemaps are supported:
<code>clos_in</code> and <code>clos_out</code>. They are for
converting TinyCLOS to and from low-level CHICKEN SWIG. Here is
a quick example:
</p>
<blockquote>
<pre>
/* Let "Shape" objects be converted back and forth from TinyCLOS into
low-level CHICKEN SWIG procedures */
%typemap(clos_in) Shape * = SIMPLE_CLOS_OBJECT *;
%typemap(clos_out) Shape * = SIMPLE_CLOS_OBJECT *;
</pre>
</blockquote>
The <code>SIMPLE_CLOS_OBJECT</code> will generally be all that
is needed ... the definition of this is as follows:
<blockquote>
<pre>
/* TinyCLOS &lt;--&gt; Low-level CHICKEN */
%typemap("clos_in") SIMPLE_CLOS_OBJECT * "(slot-ref $input (quote this))"
%typemap("clos_out") SIMPLE_CLOS_OBJECT * "(make $class (quote this) $1)"
</pre>
</blockquote>
Now, in the example using "Shape" objects, all objects
instantiated from Shape or <em>any of its subclasses fully known
to SWIG</em> will have correct TinyCLOS representations based on
<code>SIMPLE_CLOS_OBJECT</code>. SWIG "knows" the classes that
are exposed in the SWIG interface file; it "fully knows" only
those classes that are not forward declarations.
<br>
A real-world example of the "fully knows" problem is found in
the VTK visualization library. All VTK classes are derived from
vtkObject.
<blockquote>
<pre>
/* FILE: vtkObject.h */
class vtkObject {
// ...
};
</pre>
</blockquote>
<blockquote>
<pre>
/* FILE: vtkWindow.h */
#include "vtkObject.h"
class vtkWindow : public vtkObject {
// ...
};
</pre>
</blockquote>
<blockquote>
<pre>
/* FILE: vtkViewport.h */
#include "vtkViewport.h"
class vtkViewport : public vtkObject {
// ...
};
</pre>
</blockquote>
<blockquote>
<pre>
/* FILE: vtkRenderWindow.h */
#include "vtkWindow.h"
class vtkRenderer;
class vtkRenderWindow : public vtkWindow {
// ...
virtual void AddRenderer (vtkRenderer *rendererArg);
// ...
};
</pre>
</blockquote>
<blockquote>
<pre>
/* FILE: vtkRenderer.h */
#include "vtkViewport.h"
class vtkRenderWindow;
class vtkRenderer : public vtkViewport {
// ...
void SetRenderWindow(vtkRenderWindow *);
// ...
};
</pre>
</blockquote>
<blockquote>
<pre>
/* FILE: vtk.i; SWIG interface file */
%typemap(clos_in) vtkObject * = SIMPLE_CLOS_OBJECT *;
%typemap(clos_out) vtkObject * = SIMPLE_CLOS_OBJECT *;
%include "vtkObject.h"
%include "vtkWindow.h"
%include "vtkViewport.h"
%include "vtkRenderWindow.h"
%include "vtkRenderer.h"
</pre>
</blockquote>
<p>
After SWIG processes <code>vtkObject.h</code> (from the
<tt>%include "vtkObject.h"</tt> line), SWIG will have the complete
definition of the <code>vtkObject</code> class because
<code>vtkObject</code> does not contain any references to any
other classes. As it reads <code>vtkWindow.h</code> and
<code>vtkViewport.h</code>, it will already have the definition of
<code>vtkObject</code>, so it will not need a <code>clos_in</code>
or <code>clos_out</code> typemap for the <code>vtkWindow</code> or
<code>vtkViewport</code> subclasses of <code>vtkObject</code>.
However, by the time SWIG gets to <tt>%include
"vtkRenderWindow.h"</tt>, it will not have the definition for the
<code>vtkRenderer</code> class, even though it is used by
<code>vtkRenderWindow</code>. We therefore <strong>must</strong>
put in <code>clos_in/clos_out</code> typemaps for
<code>vtkRenderer</code>.
</p>
<H2><a name="Chicken_nn16"></a>17.7 Pointers</H2> <H2><a name="Chicken_nn16"></a>17.7 Pointers</H2>
@ -535,11 +378,16 @@
type. type.
</p> </p>
<H2><a name="Chicken_nn17"></a>17.8 Unsupported features</H2> <H2><a name="Chicken_nn17"></a>17.8 Unsupported features and known problems</H2>
<ul> <ul>
<li>No exception handling.</li> <li>No exception handling.</li>
<li>No director support.</li>
<li>No support for c++ standard types like std::vector.</li>
<li>No support for automatic garbage collection of wrapped classes and structures. (Planned on adding in SWIG version 1.3.24) </li>
<li>Importing multiple SWIG modules not working with TinyCLOS. (Planned on fixing for 1.3.24) </li>
<li>Problems with complicated function overloading. (Planned on fixing for 1.3.24)</li>
</ul> </ul>
</body> </body>

View file

@ -460,7 +460,7 @@
<li><a href="Chicken.html#Chicken_nn5">Code Generation</a> <li><a href="Chicken.html#Chicken_nn5">Code Generation</a>
<ul> <ul>
<li><a href="Chicken.html#Chicken_nn6">Naming Conventions</a> <li><a href="Chicken.html#Chicken_nn6">Naming Conventions</a>
<li><a href="Chicken.html#Chicken_nn7">Modules and Prefixes</a> <li><a href="Chicken.html#Chicken_nn7">Modules</a>
<li><a href="Chicken.html#Chicken_nn8">Constants and Variables</a> <li><a href="Chicken.html#Chicken_nn8">Constants and Variables</a>
<li><a href="Chicken.html#Chicken_nn9">Functions</a> <li><a href="Chicken.html#Chicken_nn9">Functions</a>
</ul> </ul>
@ -473,7 +473,7 @@
</ul> </ul>
<li><a href="Chicken.html#Chicken_nn15">Typemaps</a> <li><a href="Chicken.html#Chicken_nn15">Typemaps</a>
<li><a href="Chicken.html#Chicken_nn16">Pointers</a> <li><a href="Chicken.html#Chicken_nn16">Pointers</a>
<li><a href="Chicken.html#Chicken_nn17">Unsupported features</a> <li><a href="Chicken.html#Chicken_nn17">Unsupported features and known problems</a>
</ul> </ul>
<!-- INDEX --> <!-- INDEX -->

View file

@ -604,9 +604,10 @@ SWIG_init(int argc, C_word closure, C_word continuation) {
swig_type_list_handle = (swig_type_info **) C_block_item(sym, 0); swig_type_list_handle = (swig_type_info **) C_block_item(sym, 0);
} }
} else { } else {
C_word *a = C_alloc(C_SIZEOF_POINTER + C_SIZEOF_INTERNED_SYMBOL(C_strlen(swig_type_ptr_name)));
stable = C_new_symbol_table("swig_runtime_data" SWIG_RUNTIME_VERSION, 16); stable = C_new_symbol_table("swig_runtime_data" SWIG_RUNTIME_VERSION, 16);
sym = C_intern_in(C_heaptop, C_strlen(swig_type_ptr_name), swig_type_ptr_name, stable); sym = C_intern_in(&a, C_strlen(swig_type_ptr_name), swig_type_ptr_name, stable);
C_mutate(&C_block_item(sym, 0), C_mpointer(C_heaptop, (void *) swig_type_list_handle)); C_mutate(&C_block_item(sym, 0), C_mpointer(&a, (void *) swig_type_list_handle));
} }
for (i = 0; swig_types_initial[i]; i++) { for (i = 0; swig_types_initial[i]; i++) {

View file

@ -62,7 +62,7 @@ enum {
}; };
typedef struct swig_chicken_clientdata { typedef struct swig_chicken_clientdata {
C_word clos_class; void *gc_proxy_create;
} swig_chicken_clientdata; } swig_chicken_clientdata;
static char * static char *
@ -171,12 +171,14 @@ SWIG_Chicken_NewPointerObj(void *ptr, swig_type_info *type, int owner, C_word **
return C_SCHEME_FALSE; return C_SCHEME_FALSE;
else { else {
C_word cptr = C_swigmpointer(data, ptr, type); C_word cptr = C_swigmpointer(data, ptr, type);
if (cdata && cdata->clos_class && C_swig_is_closurep(cdata->clos_class)) { if (cdata && cdata->gc_proxy_create) {
C_save(cptr); C_word closure = CHICKEN_gc_root_ref(cdata->gc_proxy_create);
return C_callback(cdata->clos_class, 1); if (C_swig_is_closurep(closure)) {
} else { C_save(cptr);
return cptr; return C_callback(closure, 1);
}
} }
return cptr;
} }
} }

View file

@ -6,9 +6,7 @@
(cadr initargs) (cadr initargs)
(let ((ret (apply create initargs))) (let ((ret (apply create initargs)))
(if (instance? ret) (if (instance? ret)
(begin (slot-ref ret 'swig-this)
(set-finalizer! ret (lambda (x) #t))
(slot-ref ret 'swig-this))
ret))))) ret)))))
(define-class <swig-metaclass-$module> (<class>) (void)) (define-class <swig-metaclass-$module> (<class>) (void))

View file

@ -230,7 +230,7 @@ CHICKEN::top(Node *n)
Printv(f_scm,"(declare (unit ", scmmodule, "))\n\n", NIL); Printv(f_scm,"(declare (unit ", scmmodule, "))\n\n", NIL);
Printv(f_scm,"(declare \n", Printv(f_scm,"(declare \n",
tab4, "(hide swig-init)\n", tab4, "(hide swig-init)\n",
tab4, "(foreign-declare \"C_extern void swig_", module, "_init(int,C_word,C_word) C_noret;\"))\n", NIL); tab4, "(foreign-declare \"C_extern void swig_", module, "_init(C_word,C_word,C_word) C_noret;\"))\n", NIL);
Printv(f_scm,"(define swig-init (##core#primitive \"swig_", module, Printv(f_scm,"(define swig-init (##core#primitive \"swig_", module,
"_init\"))\n", NIL); "_init\"))\n", NIL);
Printv(f_scm,"(define swig-init-return (swig-init))\n\n", NIL); Printv(f_scm,"(define swig-init-return (swig-init))\n\n", NIL);
@ -360,11 +360,11 @@ CHICKEN::functionWrapper(Node *n)
Printv(f->def, Printv(f->def,
"static ", "static ",
"void ", wname, "void ", wname,
" (int argc, C_word closure, C_word continuation", " (C_word argc, C_word closure, C_word continuation",
NIL); NIL);
Printv(declfunc, Printv(declfunc,
"void ", wname, "void ", wname,
"(int,C_word,C_word", "(C_word,C_word,C_word",
NIL); NIL);
/* Generate code for argument marshalling */ /* Generate code for argument marshalling */
@ -666,11 +666,11 @@ CHICKEN::variableWrapper(Node *n) {
Printv(f->def, Printv(f->def,
"static ", "static ",
"void ",wname,"(int, C_word, C_word, C_word) C_noret;\n", "void ",wname,"(C_word, C_word, C_word, C_word) C_noret;\n",
NIL); NIL);
Printv(f->def, Printv(f->def,
"static " "static "
"void ",wname,"(int argc, C_word closure, " "void ",wname,"(C_word argc, C_word closure, "
"C_word continuation, C_word value) {\n", "C_word continuation, C_word value) {\n",
NIL); NIL);
@ -835,12 +835,12 @@ CHICKEN::constantWrapper(Node *n)
Printv(f->def, Printv(f->def,
"static ", "static ",
"void ",wname,"(int, C_word, C_word) C_noret;\n", "void ",wname,"(C_word, C_word, C_word) C_noret;\n",
NIL); NIL);
Printv(f->def, Printv(f->def,
"static ", "static ",
"void ",wname,"(int argc, C_word closure, " "void ",wname,"(C_word argc, C_word closure, "
"C_word continuation) {\n", "C_word continuation) {\n",
NIL); NIL);
@ -950,7 +950,7 @@ CHICKEN::classHandler(Node *n)
SwigType *ct = NewStringf("p.%s", Getattr(n, "name")); SwigType *ct = NewStringf("p.%s", Getattr(n, "name"));
swigtype_ptr = SwigType_manglestr(ct); swigtype_ptr = SwigType_manglestr(ct);
Printf(f_runtime, "static swig_chicken_clientdata _swig_chicken_clientdata%s = { C_SCHEME_UNDEFINED };\n", Printf(f_runtime, "static swig_chicken_clientdata _swig_chicken_clientdata%s = { 0 };\n",
mangled_classname); mangled_classname);
Printv(f_init, "SWIG_TypeClientData(SWIGTYPE", swigtype_ptr,", (void *) &_swig_chicken_clientdata", mangled_classname, ");\n", NIL); Printv(f_init, "SWIG_TypeClientData(SWIGTYPE", swigtype_ptr,", (void *) &_swig_chicken_clientdata", mangled_classname, ");\n", NIL);
SwigType_remember(ct); SwigType_remember(ct);
@ -971,7 +971,7 @@ CHICKEN::classHandler(Node *n)
Printv(closcode, "(define-method (initialize (obj ", class_name, ") initargs)\n", Printv(closcode, "(define-method (initialize (obj ", class_name, ") initargs)\n",
" (call-next-method)\n", " (call-next-method)\n",
" (swig-initialize obj initargs ", chickenPrimitiveName(newmethod), ")\n", " (swig-initialize obj initargs ", chickenPrimitiveName(newmethod), ")\n",
" (set-finalizer! obj (lambda (x) (", chickenPrimitiveName(delmethod), " (slot-ref x 'swig-this))))", //" (set-finalizer! obj (lambda (x) (", chickenPrimitiveName(delmethod), " (slot-ref x 'swig-this))))",
")\n", ")\n",
NIL); NIL);
} else { } else {
@ -995,10 +995,12 @@ CHICKEN::classHandler(Node *n)
String *closfuncname = NewString(funcname); String *closfuncname = NewString(funcname);
Replaceall(closfuncname, "_", "-"); Replaceall(closfuncname, "_", "-");
Printv(f_wrappers, "static void ", funcname, "(int,C_word,C_word,C_word) C_noret;\n", Printv(f_wrappers, "static void ", funcname, "(C_word,C_word,C_word,C_word) C_noret;\n",
"static void ", funcname, "(int argc, C_word closure, C_word continuation, C_word cl) {\n", "static void ", funcname, "(C_word argc, C_word closure, C_word continuation, C_word cl) {\n",
" C_trace(\"", funcname, "\");\n", " C_trace(\"", funcname, "\");\n",
" C_mutate(&((swig_chicken_clientdata *)(SWIGTYPE", swigtype_ptr,"->clientdata))->clos_class, cl);\n", " swig_chicken_clientdata *cdata = (swig_chicken_clientdata *) SWIGTYPE", swigtype_ptr,"->clientdata;\n",
" cdata->gc_proxy_create = CHICKEN_new_gc_root();\n",
" CHICKEN_gc_root_set(cdata->gc_proxy_create, cl);\n",
" C_kontinue(continuation, C_SCHEME_UNDEFINED);\n", " C_kontinue(continuation, C_SCHEME_UNDEFINED);\n",
"}\n", NIL); "}\n", NIL);
addMethod(closfuncname, funcname); addMethod(closfuncname, funcname);
@ -1130,12 +1132,12 @@ CHICKEN::dispatchFunction(Node *n)
Append(wname, Swig_name_wrapper(iname)); Append(wname, Swig_name_wrapper(iname));
Printv(f->def, "static void real_", wname, Printv(f->def, "static void real_", wname,
"(int, C_word, C_word, C_word) C_noret;\n", NIL); "(C_word, C_word, C_word, C_word) C_noret;\n", NIL);
Printv(f->def, Printv(f->def,
"static void real_", "static void real_",
wname, wname,
"(int, C_word closure, C_word continuation, C_word args) {", "(C_word oldargc, C_word closure, C_word continuation, C_word args) {",
NIL); NIL);
Wrapper_add_local(f,"argc","int argc"); Wrapper_add_local(f,"argc","int argc");
@ -1164,9 +1166,9 @@ CHICKEN::dispatchFunction(Node *n)
/* varargs */ /* varargs */
Printv(f->def, "void ", wname, Printv(f->def, "void ", wname,
"(int, C_word, C_word, ...) C_noret;\n", NIL); "(C_word, C_word, C_word, ...) C_noret;\n", NIL);
Printv(f->def, "void ", wname, Printv(f->def, "void ", wname,
"(int c, C_word t0, C_word t1, ...) {", "(C_word c, C_word t0, C_word t1, ...) {",
NIL); NIL);
Printv(f->code, Printv(f->code,
"C_word t2;\n", "C_word t2;\n",