diff options
Diffstat (limited to 'Examples/tcl/pointer')
| -rw-r--r-- | Examples/tcl/pointer/Makefile | 19 | ||||
| -rw-r--r-- | Examples/tcl/pointer/example.c | 16 | ||||
| -rw-r--r-- | Examples/tcl/pointer/example.i | 31 | ||||
| -rw-r--r-- | Examples/tcl/pointer/index.html | 171 | ||||
| -rw-r--r-- | Examples/tcl/pointer/runme.tcl | 47 |
5 files changed, 284 insertions, 0 deletions
diff --git a/Examples/tcl/pointer/Makefile b/Examples/tcl/pointer/Makefile new file mode 100644 index 0000000..bed049a --- /dev/null +++ b/Examples/tcl/pointer/Makefile @@ -0,0 +1,19 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +SRCS = example.c +TARGET = my_tclsh +DLTARGET = example +INTERFACE = example.i + +all:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + TARGET='$(DLTARGET)' INTERFACE='$(INTERFACE)' tcl + +static:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' tclsh + +clean:: + $(MAKE) -f $(TOP)/Makefile tcl_clean + +check: all diff --git a/Examples/tcl/pointer/example.c b/Examples/tcl/pointer/example.c new file mode 100644 index 0000000..b877d9a --- /dev/null +++ b/Examples/tcl/pointer/example.c @@ -0,0 +1,16 @@ +/* File : example.c */ + +void add(int *x, int *y, int *result) { + *result = *x + *y; +} + +void sub(int *x, int *y, int *result) { + *result = *x - *y; +} + +int divide(int n, int d, int *r) { + int q; + q = n/d; + *r = n - q*d; + return q; +} diff --git a/Examples/tcl/pointer/example.i b/Examples/tcl/pointer/example.i new file mode 100644 index 0000000..4d5b523 --- /dev/null +++ b/Examples/tcl/pointer/example.i @@ -0,0 +1,31 @@ +/* File : example.i */ +%module example + +%{ +extern void add(int *, int *, int *); +extern void sub(int *, int *, int *); +extern int divide(int, int, int *); +%} + +/* This example illustrates a couple of different techniques + for manipulating C pointers */ + +/* First we'll use the pointer library */ +extern void add(int *x, int *y, int *result); + +%include cpointer.i +%pointer_functions(int, intp); + +/* Next we'll use some typemaps */ + +%include typemaps.i +extern void sub(int *INPUT, int *INPUT, int *OUTPUT); + +/* Next we'll use typemaps and the %apply directive */ + +%apply int *OUTPUT { int *r }; +extern int divide(int n, int d, int *r); + + + + diff --git a/Examples/tcl/pointer/index.html b/Examples/tcl/pointer/index.html new file mode 100644 index 0000000..874088a --- /dev/null +++ b/Examples/tcl/pointer/index.html @@ -0,0 +1,171 @@ +<html> +<head> +<title>SWIG:Examples:tcl:pointer</title> +</head> + +<body bgcolor="#ffffff"> + +<tt>SWIG/Examples/tcl/pointer/</tt> +<hr> + +<H2>Simple Pointer Handling</H2> + +<p> +This example illustrates a couple of techniques for handling +simple pointers in SWIG. The prototypical example is a C function +that operates on pointers such as this: + +<blockquote> +<pre> +void add(int *x, int *y, int *r) { + *r = *x + *y; +} +</pre> +</blockquote> + +By default, SWIG wraps this function exactly as specified and creates +an interface that expects pointer objects for arguments. The only +problem is how does one go about creating these objects from a script? + +<h2>Possible Solutions</h2> + +<ul> +<li>Write some helper functions to explicitly create objects. For +example: + +<blockquote> +<pre> +int *new_int(int ivalue) { + int *i = (int *) malloc(sizeof(ivalue)); + *i = ivalue; + return i; +} +int get_int(int *i) { + return *i; +} + +void delete_int(int *i) { + free(i); +} +</pre> +</blockquote> + +Now, in a script you would do this: + +<blockquote> +<pre> +set a [new_int 37] +set b [new_int 42] +set c [new_int 0] +add $a $b $c +set r [get_int $c] +puts "Result = $r" +delete_int $a +delete_int $b +delete_int $c +</pre> +</blockquote> + +<p> +<li>Use the SWIG pointer library. For example, in the interface file +you would do this: + +<blockquote> +<pre> +%include "pointer.i" +</pre> +</blockquote? + +and in a script you would do this: + +<blockquote> +<pre> +set a [ptrcreate int 37] +set b [ptrcreate int 42] +set c [ptrcreate int] +add $a $b $c +set r [ptrvalue $c] +puts "Result = $r" +ptrfree $a +ptrfree $b +ptrfree $c +</pre> +</blockquote> + +The advantage to using the pointer library is that it unifies some of the helper +functions behind a common set of names. For example, the same set of functions work +with int, double, float, and other fundamental types. + +<p> +<li>Use the SWIG typemap library. This library allows you to completely +change the way arguments are processed by SWIG. For example: + +<blockquote> +<pre> +%include "typemaps.i" +void add(int *INPUT, int *INPUT, int *OUTPUT); +</pre> +</blockquote> + +And in a script: + +<blockquote> +<pre> +set r [add 37 42] +puts "Result = $r" +</pre> +</blockquote> +Needless to say, this is substantially easier. + +<p> +<li>A final alternative is to use the typemaps library in combination +with the %apply directive. This allows you to change the names of parameters +that behave as input or output parameters. For example: + +<blockquote> +<pre> +%include "typemaps.i" +%apply int *INPUT {int *x, int *y}; +%apply int *OUTPUT {int *r}; + +void add(int *x, int *y, int *r); +void sub(int *x, int *y, int *r); +void mul(int *x, int *y, int *r); +... etc ... +</pre> +</blockquote> + +</ul> + +<h2>Example</h2> + +The following example illustrates the use of these features for pointer +extraction. + +<ul> +<li> <a href="example.c">example.c</a> (C Source) +<li> <a href="example.i">example.i</a> (Swig interface) +<li> <a href="runme.tcl">runme.tcl</a> (Tcl Script) +</ul> + +<h2>Notes</h2> + +<ul> +<li>Since pointers are used for so many different things (arrays, output values, +etc...) the complexity of pointer handling can be as complicated as you want to +make it. + +<p> +<li>More documentation on the typemaps.i and pointer.i library files can be +found in the SWIG user manual. The files also contain documentation. + +<p> +<li>The pointer.i library is designed primarily for convenience. If you +are concerned about performance, you probably want to use a different +approach. + +</ul> + +<hr> +</body> +</html> diff --git a/Examples/tcl/pointer/runme.tcl b/Examples/tcl/pointer/runme.tcl new file mode 100644 index 0000000..efe9bb4 --- /dev/null +++ b/Examples/tcl/pointer/runme.tcl @@ -0,0 +1,47 @@ +# file: runme.tcl + +catch { load ./example[info sharedlibextension] example} + +# First create some objects using the pointer library. +puts "Testing the pointer library" +set a [new_intp] +set b [new_intp] +set c [new_intp] ;# Memory for result + +intp_assign $a 37 +intp_assign $b 42 + +puts " a = $a" +puts " b = $b" +puts " c = $c" + +# Call the add() function with some pointers +add $a $b $c + +# Now get the result +set r [intp_value $c] +puts " 37 + 42 = $r" + +# Clean up the pointers +delete_intp $a +delete_intp $b +delete_intp $c + +# Now try the typemap library +# This should be much easier. Now how it is no longer +# necessary to manufacture pointers. + +puts "Trying the typemap library" +set r [sub 37 42] +puts " 37 - 42 = $r" + +# Now try the version with multiple return values + +puts "Testing multiple return values" +set qr [divide 42 37] +set q [lindex $qr 0] +set r [lindex $qr 1] +puts " 42/37 = $q remainder $r" + + + |
