diff options
Diffstat (limited to 'Examples/tcl/funcptr')
| -rw-r--r-- | Examples/tcl/funcptr/Makefile | 19 | ||||
| -rw-r--r-- | Examples/tcl/funcptr/example.c | 19 | ||||
| -rw-r--r-- | Examples/tcl/funcptr/example.h | 9 | ||||
| -rw-r--r-- | Examples/tcl/funcptr/example.i | 16 | ||||
| -rw-r--r-- | Examples/tcl/funcptr/index.html | 90 | ||||
| -rw-r--r-- | Examples/tcl/funcptr/runme.tcl | 21 |
6 files changed, 174 insertions, 0 deletions
diff --git a/Examples/tcl/funcptr/Makefile b/Examples/tcl/funcptr/Makefile new file mode 100644 index 0000000..bed049a --- /dev/null +++ b/Examples/tcl/funcptr/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/funcptr/example.c b/Examples/tcl/funcptr/example.c new file mode 100644 index 0000000..5c4a3da --- /dev/null +++ b/Examples/tcl/funcptr/example.c @@ -0,0 +1,19 @@ +/* File : example.c */ + +int do_op(int a, int b, int (*op)(int,int)) { + return (*op)(a,b); +} + +int add(int a, int b) { + return a+b; +} + +int sub(int a, int b) { + return a-b; +} + +int mul(int a, int b) { + return a*b; +} + +int (*funcvar)(int,int) = add; diff --git a/Examples/tcl/funcptr/example.h b/Examples/tcl/funcptr/example.h new file mode 100644 index 0000000..9936e24 --- /dev/null +++ b/Examples/tcl/funcptr/example.h @@ -0,0 +1,9 @@ +/* file: example.h */ + +extern int do_op(int,int, int (*op)(int,int)); +extern int add(int,int); +extern int sub(int,int); +extern int mul(int,int); + +extern int (*funcvar)(int,int); + diff --git a/Examples/tcl/funcptr/example.i b/Examples/tcl/funcptr/example.i new file mode 100644 index 0000000..8b3bef6 --- /dev/null +++ b/Examples/tcl/funcptr/example.i @@ -0,0 +1,16 @@ +/* File : example.i */ +%module example +%{ +#include "example.h" +%} + +/* Wrap a function taking a pointer to a function */ +extern int do_op(int a, int b, int (*op)(int, int)); + +/* Now install a bunch of "ops" as constants */ +%constant int (*ADD)(int,int) = add; +%constant int (*SUB)(int,int) = sub; +%constant int (*MUL)(int,int) = mul; + +extern int (*funcvar)(int,int); + diff --git a/Examples/tcl/funcptr/index.html b/Examples/tcl/funcptr/index.html new file mode 100644 index 0000000..b822962 --- /dev/null +++ b/Examples/tcl/funcptr/index.html @@ -0,0 +1,90 @@ +<html> +<head> +<title>SWIG:Examples:tcl:funcptr</title> +</head> + +<body bgcolor="#ffffff"> + + +<tt>SWIG/Examples/tcl/funcptr/</tt> +<hr> + +<H2>Pointers to Functions</H2> + +<p> +Okay, just what in the heck does SWIG do with a declaration like this? + +<blockquote> +<pre> +int do_op(int a, int b, int (*op)(int, int)); +</pre> +</blockquote> + +Well, it creates a wrapper as usual. Of course, that does raise some +questions about the third argument (the pointer to a function). + +<p> +In this case, SWIG will wrap the function pointer as it does for all other +pointers. However, in order to actually call this function from a script, +you will need to pass some kind of C function pointer object. In C, +this is easy, you just supply a function name as an argument like this: + +<blockquote> +<pre> +/* Some callback function */ +int add(int a, int b) { + return a+b; +} +... +int r = do_op(x,y,add); +</pre> +</blockquote> + +To make this work with SWIG, you will need to do a little extra work. Specifically, +you need to create some function pointer objects using the %constant directive like this: + +<blockquote> +<pre> +%constant(int (*)(int,int)) ADD = add; +</pre> +</blockquote> + +Now, in a script, you would do this: + +<blockquote> +<pre> +set r [do_op $x $y $ADD] +</pre> +</blockquote> + +<h2>An Example</h2> + +Here are some files that illustrate this with a simple example: + +<ul> +<li><a href="example.c">example.c</a> +<li><a href="example.h">example.h</a> +<li><a href="example.i">example.i</a> (SWIG interface) +<li><a href="runme.tcl">runme.tcl</a> (Sample script) +</ul> + +<h2>Notes</h2> + +<ul> +<li>The value of a function pointer must correspond to a function written in C or C++. +It is not possible to pass an arbitrary Tcl function object in as a substitute for a C +function pointer. + +<p> +<li>A Tcl function can be used as a C/C++ callback if you write some +clever typemaps and are very careful about how you create your extension. +This is an advanced topic not covered here. +</ul> + +<hr> +</body> +</html> + + + + diff --git a/Examples/tcl/funcptr/runme.tcl b/Examples/tcl/funcptr/runme.tcl new file mode 100644 index 0000000..7e676c2 --- /dev/null +++ b/Examples/tcl/funcptr/runme.tcl @@ -0,0 +1,21 @@ +# file: runme.tcl + +catch { load ./example[info sharedlibextension] example} + +set a 37 +set b 42 + +# Now call our C function with a bunch of callbacks + +puts "Trying some C callback functions" +puts " a = $a" +puts " b = $b" +puts " ADD(a,b) = [do_op $a $b $ADD]" +puts " SUB(a,b) = [do_op $a $b $SUB]" +puts " MUL(a,b) = [do_op $a $b $MUL]" + +puts "Here is what the C callback function objects look like in Tcl" +puts " ADD = $ADD" +puts " SUB = $SUB" +puts " MUL = $MUL" + |
