- Improve the runtime type sytesm

- Update all languages to new type system
- Add DohSortList function
- Fix mzscheme Examples/Makefile


git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@6930 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
John Lenz 2005-02-01 00:08:24 +00:00
commit f6964f285f
48 changed files with 1383 additions and 1021 deletions

152
SWIG/Doc/Devel/runtime.txt Normal file
View file

@ -0,0 +1,152 @@
This file describes the necissary functions and interfaces a language module
needs to implement to take advantage of the run time type system. I assume you
have read the run-time section of the Typemaps chapter in the SWIG
documentation.
Last updated: January 23, 2005
The file we are concerned with here should be named langrun.swg. A good example
of a simple file is the Lib/mzscheme/mzrun.swg file. First, a few requirements
and notes:
1) Every function in this file should be declared static.
2) It should be inserted into the runtime section of the _wrap file from your
config file. The Lib/swigrun.swg file should be included before this file.
That is, you need to have
%runtime "swigrun.swg"
%runtime "langrun.swg"
3) You must also include the swiginit.swg file in the init section of the
wrapper. That is, you should have
%insert(init) "swiginit.swg"
4) From module.cxx, you need to call the SwigType_emit_type_table function, as
well as register types with SwigType_remember or SwigType_remember_clientdata
5) By convention, all functions in this file are of the form
SWIG_Language_Whatever, and #defines are used to rename SWIG API functions to
these function names
6) You need to call void SWIG_InitializeModule(void *clientdata) from your init
function.
-------------------------------------------------------------------------------
Required Functions
-------------------------------------------------------------------------------
swig_module_info *SWIG_GetModule(void *clientdata);
void SWIG_SetModule(void *clientdata, swig_module_info *mod);
The SetModule function should store the mod argument into some globally
accessable variable in the target language. The action of these two functions
is to provide a way for multiple modules to share information. The SetModule
function should create a new global var named something like
"swig_runtime_data_type_pointer" SWIG_RUNTIME_VERSION SWIG_TYPE_TABLE_NAME
SWIG_RUNTIME_VERSION is currently defined as "2", and SWIG_TYPE_TABLE_NAME is
defined by the -DSWIG_TYPE_TABLE=mytable option when compiling the wrapper.
Alternativly, if the language supports modules, a module named
"swig_runtime_data" SWIG_RUNTIME_VERSION can be created, and a global variable
named "type_table" SWIG_TYPE_TABLE_NAME can be created inside it. The most
common approach is to store the mod pointer in some global variable in the
target language, but if the language provides an alternative place to store data
(like the chicken module), then that is good too.
The way the code is set up, SetModule should only be called when GetModule
returns NULL, and if SetModule is called a second time, the behavior is
undefined. Just make sure it doesn't crash in the random chance occurance that
SetModule is called twice.
There are two options here.
1) The perferred approach is for GetModule and SetModule to not require a
clientdata pointer. If you can at all avoid it, please do so. Here, you would
write swig_module_info *SWIG_Language_GetModule();
void SWIG_Language_SetModule(swig_module_info *mod);
and then add
#define SWIG_GetModule(clientdata) SWIG_Language_GetModule()
#define SWIG_SetModule(cd, ptr) SWIG_Language_SetModule(ptr)
You would then call
SWIG_InitializeModule(0)
2) If GetModule and SetModule need to take a custom pointer (most notably an
environment pointer, see tcl or mzscheme), then you should write
swig_module_info *SWIG_Language_GetModule(void *clientdata)
void SWIG_Langauge_SetModule(void *clientdata, swig_module_info *mod);
and also define
#define SWIG_GetModule(cd) SWIG_Langauge_GetModule(cd)
#define SWIG_SetModule(cd, ptr) SWIG_Language_SetModule(cd, ptr)
#define SWIG_MODULE_CLIENTDATA_TYPE Whatever
SWIG_MODULE_CLIENTDATA_TYPE should be defined to whatever the type of
clientdata is.
You would then call SWIG_InitializeModule(clientdata), and clientdata would get
passed to GetModule and SetModule. clientdata will not be stored and will only
be referenced during the InitializeModule call. After InitializeModule returns,
clientdata does not need to be valid any more.
This method is not preferred, because it makes external access to the type
system more complicated. See the Modules chapter of the documentation, and read
the "External access to the run-time" section. Then take a look at
Lib/runtime.swg. Anybody that calls SWIG_TypeQuery needs to pass along the
clientdata pointer, and that is the reason for defining
SWIG_MODULE_CLIENTDATA_TYPE.
-------------------------------------------------------------------------------
Standard Functions
-------------------------------------------------------------------------------
These functions are not required and their API is not formalized, but almost all
language modules implement them for consistancy across languages. Throughout
this discussion, I will use LangType to represent the underlying language type
(C_word in chicken, Scheme_Object * in mzscheme, PyObject * in python, etc)
LangObj SWIG_NewPointerObj(void *ptr, swig_type_info *type, int flags);
Create and return a new pointer object that has both ptr and type. For almost
all language modules, flags is used for ownership. If flags==1, then the
created pointer should be registered to be garbage collected.
int SWIG_ConvertPtr(LangType obj, void **result, swig_type_info *type, int flags);
Convert a language wrapped pointer into a void *. The pointer is returned in
result, and the function should return 0 on success, non-zero on error.
A sample ConvertPtr is given here:
swig_cast_info *cast;
if (<obj is a wrapped pointer type>) {
cast = SWIG_TypeCheck(<obj type name>, type);
cast = SWIG_TypeCheckStruct(<obj type structure>, type);
if (cast) {
*result = SWIG_TypeCast(cast, <obj pointer>);
return 0;
}
}
return 1;
Either TypeCheck or TypeCheckStruct can be called, depending on how the pointer
is wrapped in langtype. If obj stores the void pointer and the type name, then
the TypeCheck function should be used, while if obj stores the void pointer and
a pointer to the swig_type_info structure, then the TypeCheckStruct function
should be called. The TypeCheckStruct is slightly faster, since it does a
pointer comparison instead of a strcmp.
void *SWIG_MustGetPtr(LangType obj, swig_type_info *type, int flags,
int argnum, const char *func_name) {
void *result;
if (SWIG_ConvertPtr(s, &result, type, flags)) {
generate runtime type error ("Error in func_name, expected a" +
type->str ? type->str : "void *" +
"at argument number" + argnum);
}
return result;
}
This function is optional, and the number and type of parameters can be
different, but is useful for typemap purposes:
%typemap(in) SWIGTYPE *, SWIGTYPE &, SWIGTYPE [] {
$1 = ($1_ltype)SWIG_MustGetPtr($input, $descriptor, 0, $argnum, FUNC_NAME);
}

View file

@ -388,28 +388,36 @@ If the Scheme object passed was not a SWIG smob representing a compatible
pointer, a <code>wrong-type-arg</code> exception is raised.
<H3><a name="Guile_nn13"></a>18.6.1 GH Smobs</H3>
<p>
In earlier versions of SWIG, C pointers were represented as Scheme
strings containing a hexadecimal rendering of the pointer value and a
mangled type name. As Guile allows registering user types, so-called
"smobs" (small objects), a much cleaner representation has been
implemented now. The details will be discussed in the following.
</p>
<p>
A smob is a cons cell where the lower half of the CAR contains the
smob type tag, while the upper half of the CAR and the whole CDR are
available. <code>SWIG_Guile_Init()</code> registers a smob type named
"swig" with Guile; its type tag is stored in the variable
<code>swig_tag</code>. The upper half of the CAR store an index into
a table of all C pointer types seen so far, to which new types seen
are appended. The CDR stores the pointer value.
<p> A smob is a cons cell where the lower half of the CAR contains the smob type
tag, while the upper half of the CAR and the whole CDR are available. Every
module creates its own smob type in the clientdata field of the module. So the
lower 16 bits of the car of the smob store the tag and the upper 16 bits store
the index this type is in the array. We can then, given a smob, find its
swig_type_info struct by using the tag (lower 16 bits of car) to find which
module this type is in (since each tag is unique for the module). Then we use
the upper 16 bits to index into the array of types attached to this module.
Looking up the module from the tag is worst case O(# of modules) but average
case O(1). This is because the modules are stored in a circularly linked list,
and when we start searching the modules for the tag, we start looking with the
module that the function doing the lookup is in. SWIG_Guile_ConvertPtr() takes
as its first argument the swig_module_info * of the calling function, which is
where we start comparing tags. Most types will be looked up in the same module
that created them, so the first module we check will most likely be correct.
Once we have a swig_type_info structure, we loop through the linked list of
casts, using pointer comparisons.</p>
<H3><a name="Guile_nn14"></a>18.6.2 SCM Smobs</H3>
<p>The SCM interface (using the "-scm" argument to swig) uses common.swg.
<p>The SCM interface (using the "-scm" argument to swig) uses swigrun.swg.
The whole type system, when it is first initialized, creates two smobs named "swig" and "collected_swig".
The swig smob is used for non-garbage collected smobs, while the collected_swig smob is used as described
below. Each smob has the same format, which is a double cell created by SCM_NEWSMOB2()

View file

@ -9,9 +9,10 @@
<!-- INDEX -->
<ul>
<li><a href="#Modules_nn2">The SWIG runtime code</a>
<li><a href="#Modules_nn3">A word of caution about static libraries</a>
<li><a href="#Modules_nn4">References</a>
<li><a href="#Modules_nn5">Reducing the wrapper file size</a>
<li><a href="#external_run_time">External access to runtime system</a>
<li><a href="#Modules_nn4">A word of caution about static libraries</a>
<li><a href="#Modules_nn5">References</a>
<li><a href="#Modules_nn6">Reducing the wrapper file size</a>
</ul>
<!-- INDEX -->
@ -68,7 +69,52 @@ Be careful if you use threads and the automatic module loading that some scripti
languages provide. One solution is to load all modules before spawning any threads.
</p>
<H2><a name="Modules_nn3"></a>15.2 A word of caution about static libraries</H2>
<H2><a name="external_run_time"></a>15.2 External access to the run-time system</a></H2>
<p>As described in <a href="Typemaps.html#runtime_type_checker">The run-time type checker</a>,
the functions <tt>SWIG_TypeQuery</tt>, <tt>SWIG_NewPointerObj</tt>, and others sometimes need
to be called. Calling these functions from a typemap is supported, since the typemap code
is embedded into the <tt>_wrap.c</tt> file, which has those declerations available. If you need
to call the SWIG run-time functions from another C file, there are three headers you need
to include. They are located in the Lib directory in the SWIG source, or wherever the
SWIG Library was installed. You can see the current library path by running
<tt>swig -swiglib</tt>.</p>
<blockquote><pre>
#include &lt;swigrun.swg&gt;
#include &lt;python/pyrun.swg&gt; /* Or other header, see below */
#include &lt;runtime.swg&gt;
</pre></blockquote>
<p>After including these three headers, your code should be able to call <tt>SWIG_TypeQuery</tt>,
<tt>SWIG_NewPointerObj</tt>, <tt>SWIG_ConvertPtr</tt> and others. The exact argument paramaters
for these functions might differ between language modules; please check the language module chapters
for more information.</p>
<p>Inside these headers the functions are declared static and are included inline into the file,
and thus the file does not need to be linked against any SWIG libraries or code (you might still
need to link against the language libraries like libpython-2.3). Data is shared between this
file and the _wrap.c files through a global variable in the wrapping language. It is also
possible to copy these three header files into your own package for distribution along with
the generated wrapper files, so that you can distribute a package that can be compiled
without SWIG installed (this works because the header files are self contained, and do not
need to link with anything).</p>
<p>The headers that should be included in place of the #include &lt;python/pyrun.swg&gt;
for the different language modules are:</p>
<ul>
<li>Chicken - &lt;chicken/chickenrun.swg&gt;</li>
<li>Guile (scm) - &lt;guile/guile_scm_run.swg&gt;</li>
<li>Guile (gh) - This does not work with the -gh API, use the -scm API</li>
<li>MzScheme - &lt;mzscheme/mzrun.swg&gt;</li>
<li>Ocaml - &lt;ocaml/ocaml.swg&gt;</li>
<li>Python - &lt;python/pyrun.swg&gt;</li>
<li>Perl5 - &lt;perl5/perlrun.swg&gt;</li>
<li>Ruby - &lt;ruby/rubydef.swg&gt;</li>
<li>Tcl - &lt;tcl/swigtcl8.swg&gt;</li>
</ul>
<H2><a name="Modules_nn4"></a>15.3 A word of caution about static libraries</H2>
When working with multiple SWIG modules, you should take care not to use static
@ -77,13 +123,13 @@ of SWIG modules with that library, each module will get its own private copy of
into it. This is very often <b>NOT</b> what you want and it can lead to unexpected or bizarre program
behavior. When working with dynamically loadable modules, you should try to work exclusively with shared libaries.
<H2><a name="Modules_nn4"></a>15.3 References</H2>
<H2><a name="Modules_nn5"></a>15.4 References</H2>
Due to the complexity of working with shared libraries and multiple modules, it might be a good idea to consult
an outside reference. John Levine's "Linkers and Loaders" is highly recommended.
<H2><a name="Modules_nn5"></a>15.4 Reducing the wrapper file size</H2>
<H2><a name="Modules_nn6"></a>15.5 Reducing the wrapper file size</H2>
<p>

View file

@ -2540,6 +2540,24 @@ ordering (and perform conversions if needed).
<H2><a name="runtime_type_checker"></a>10.8 The run-time type checker</H2>
Most scripting languages need type information at run-time. This type information
can include how to construct types, how to garbage collect types, and the inheritance
relationships between types. If the language interface does not provide its own type
information storage, the generated SWIG code needs to provide it.<br><br>
Requirements for the type system:<br>
<li>Store inheritance and type equivalence information and be able to correctly
re-create the type pointer.</li>
<li>Share type information between modules.</li>
<li>Modules can be loaded in any order, irregardless of actual type
dependency.</li>
<li>Avoid the use of dynamically allocated memory, and library/system calls in general.</li>
<li>Provide a reasonably fast implementation, minimizing the lookup time for all
language modules.</li>
<li>Custom, language specific information can be attached to types.</li>
<li>Modules can be unloaded from the type system.</li>
<H3>8.8.1 Implementation</H3>
<p>
The run-time type checker is used by many, but not all, of SWIG's supported target languages.
@ -2628,7 +2646,90 @@ pointer. However, the exact name and calling conventions of the conversion
function depends on the target language (see language specific chapters for details).
<p>
When pointers are converted in a typemap, the typemap code often looks
The actual type code is in swigrun.swg, and gets inserted near the top of the generated
swig wrapper file. The phrase "a type X that can cast into a type Y" means
that given a type X, it can be converted into a type Y. In other words, X is a derived
class of Y or X is a typedef of Y. The structure to store type information looks like this:
<blockquote>
<pre>
/* Structure to store information on one type */
typedef struct swig_type_info {
const char *name; /* mangled name of this type */
const char *str; /* human readable name for this type */
swig_dycast_func dcast; /* dynamic cast function down a hierarchy */
struct swig_cast_info *cast; /* Linked list of types that can cast into this type */
void *clientdata; /* Language specific type data */
} swig_type_info;
/* Structure to store a type and conversion function used for casting */
typedef struct swig_cast_info {
swig_type_info *type; /* pointer to type that is equivalent to this type */
swig_converter_func converter; /* function to cast the void pointers */
struct swig_cast_info *next; /* pointer to next cast in linked list */
struct swig_cast_info *prev; /* pointer to the previous cast */
} swig_cast_info;
</pre>
</blockquote>
Each <tt>swig_type_info</tt> stores a linked list of types that it is equivalent to. Each entry in this
doubly linked list stores a pointer back to another swig_type_info structure,
along with a pointer to a conversion function. This conversion function is used
to solve the above problem of the FooBar class, correctly returning a pointer to
the type we want.
<p>
The basic problem we need to solve is verifying and building arguments passed to functions.
So going back to the <tt>SWIG_ConvertPtr()</tt> function example from above, we are
expecting a <tt>Foo *</tt> and need to
check if <tt>obj0</tt> is in fact a <tt>Foo *</tt>. From before, <tt>SWIGTYPE_p_Foo</tt> is just
a pointer to the <tt>swig_type_info</tt> structure describing <tt>Foo *</tt>. So we loop though the
linked list of <tt>swig_cast_info</tt> structures attached to <tt>SWIGTYPE_p_Foo</tt>. If we see that the type of <tt>obj0</tt> is in the
linked list, we pass the object through the associated conversion function and
then return a positive. If we reach the end of the linked list without a match,
then <tt>obj0</tt> can not be converted to a <tt>Foo *</tt> and an error is generated.
<p>
Another issue needing to be addressed is sharing type information between multiple modules.
More explicitly, we need
to have ONE <tt>swig_type_info</tt> for each type. If two modules both use the type, the
second module loaded must lookup and use the swig_type_info structure from the module already loaded.
Because no dynamic memory is used and the circular dependencies of the
casting information, loading the type information is somewhat tricky, and not explained here.
A complete description is in the <tt>common.swg</tt> file (and near the top of any generated file).
<br><br>
Each module has one swig_module_info structure which looks like this:
<blockquote>
<pre>
/* Structure used to store module information
* Each module generates one structure like this, and the runtime collects
* all of these structures and stores them in a circularly linked list.*/
typedef struct swig_module_info {
swig_type_info **types; /* Array of pointers to swig_type_info structures that are in this module */
int size; /* Number of types in this module */
struct swig_module_info *next; /* Pointer to next element in circularly linked list */
swig_type_info **type_initial; /* Array of initially generated type structures */
swig_cast_info **cast_initial; /* Array of initially generated casting structures */
void *clientdata; /* Language specific module data */
} swig_module_info;
</pre>
</blockquote>
Each module stores an array of pointers to <tt>swig_type_info</tt> structures and the number of
types in this module. So when a second module is loaded, it finds the <tt>swig_module_info</tt>
structure for the first module and searches the array of types. If any of its own
types are in the first module and have already been loaded, it uses those <tt>swig_type_info</tt>
structures rather than creating new ones. These <tt>swig_module_info</tt>
structures are chained together in a circularly linked list.
<a name="n43"></a><H3>8.8.2 Usage</H3>
<p>This section covers how to use these functions from typemaps. To learn how to
call these functions from external files (not the generated _wrap.c file), see
the <a href="Modules.html#external_run_time">External access to the run-time system</a>
section.</p>
<p>When pointers are converted in a typemap, the typemap code often looks
similar to this:
</p>