summaryrefslogtreecommitdiff
path: root/Examples/tcl/funcptr
diff options
context:
space:
mode:
Diffstat (limited to 'Examples/tcl/funcptr')
-rw-r--r--Examples/tcl/funcptr/Makefile19
-rw-r--r--Examples/tcl/funcptr/example.c19
-rw-r--r--Examples/tcl/funcptr/example.h9
-rw-r--r--Examples/tcl/funcptr/example.i16
-rw-r--r--Examples/tcl/funcptr/index.html90
-rw-r--r--Examples/tcl/funcptr/runme.tcl21
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"
+