- 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:
parent
58cd593dae
commit
f6964f285f
48 changed files with 1383 additions and 1021 deletions
152
SWIG/Doc/Devel/runtime.txt
Normal file
152
SWIG/Doc/Devel/runtime.txt
Normal 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);
|
||||
}
|
||||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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 <swigrun.swg>
|
||||
#include <python/pyrun.swg> /* Or other header, see below */
|
||||
#include <runtime.swg>
|
||||
</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 <python/pyrun.swg>
|
||||
for the different language modules are:</p>
|
||||
<ul>
|
||||
<li>Chicken - <chicken/chickenrun.swg></li>
|
||||
<li>Guile (scm) - <guile/guile_scm_run.swg></li>
|
||||
<li>Guile (gh) - This does not work with the -gh API, use the -scm API</li>
|
||||
<li>MzScheme - <mzscheme/mzrun.swg></li>
|
||||
<li>Ocaml - <ocaml/ocaml.swg></li>
|
||||
<li>Python - <python/pyrun.swg></li>
|
||||
<li>Perl5 - <perl5/perlrun.swg></li>
|
||||
<li>Ruby - <ruby/rubydef.swg></li>
|
||||
<li>Tcl - <tcl/swigtcl8.swg></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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue