diff options
Diffstat (limited to 'Examples/ruby/pointer')
-rw-r--r-- | Examples/ruby/pointer/Makefile | 18 | ||||
-rw-r--r-- | Examples/ruby/pointer/example.c | 16 | ||||
-rw-r--r-- | Examples/ruby/pointer/example.i | 30 | ||||
-rw-r--r-- | Examples/ruby/pointer/index.html | 171 | ||||
-rw-r--r-- | Examples/ruby/pointer/runme.rb | 45 |
5 files changed, 280 insertions, 0 deletions
diff --git a/Examples/ruby/pointer/Makefile b/Examples/ruby/pointer/Makefile new file mode 100644 index 0000000..8c4fe10 --- /dev/null +++ b/Examples/ruby/pointer/Makefile @@ -0,0 +1,18 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +SRCS = example.c +TARGET = example +INTERFACE = example.i + +all:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' ruby + +static:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + TARGET='myruby' INTERFACE='$(INTERFACE)' ruby_static + +clean:: + $(MAKE) -f $(TOP)/Makefile ruby_clean + +check: all diff --git a/Examples/ruby/pointer/example.c b/Examples/ruby/pointer/example.c new file mode 100644 index 0000000..b877d9a --- /dev/null +++ b/Examples/ruby/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/ruby/pointer/example.i b/Examples/ruby/pointer/example.i new file mode 100644 index 0000000..a8ac794 --- /dev/null +++ b/Examples/ruby/pointer/example.i @@ -0,0 +1,30 @@ +/* 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/ruby/pointer/index.html b/Examples/ruby/pointer/index.html new file mode 100644 index 0000000..2b9c40b --- /dev/null +++ b/Examples/ruby/pointer/index.html @@ -0,0 +1,171 @@ +<html> +<head> +<title>SWIG:Examples:ruby:pointer</title> +</head> + +<body bgcolor="#ffffff"> + +<tt>SWIG/Examples/ruby/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> +a = new_int(37) +b = new_int(42) +c = new_int(0) +add(a,b,c) +r = get_int(c) +print "Result = #{r}\n" +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> +a = ptrcreate("int",37) +b = ptrcreate("int",42) +c = ptrcreate("int") +add(a,b,c) +r = ptrvalue(c) +print "Result = #{r}\n" +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> +r = add(37,42) +print "Result = #{r}\n" +</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.rb">runme.rb</a> (Ruby 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/ruby/pointer/runme.rb b/Examples/ruby/pointer/runme.rb new file mode 100644 index 0000000..d696b02 --- /dev/null +++ b/Examples/ruby/pointer/runme.rb @@ -0,0 +1,45 @@ +# file: runme.rb + +require 'example' + +# First create some objects using the pointer library. +print "Testing the pointer library\n" +a = Example::new_intp() +b = Example::new_intp() +c = Example::new_intp() + +Example::intp_assign(a,37) +Example::intp_assign(b,42) + +print " a = #{a}\n" +print " b = #{b}\n" +print " c = #{c}\n" + +# Call the add() function with some pointers +Example::add(a, b, c) + +# Now get the result +r = Example::intp_value(c) +print " 37 + 42 = #{r}\n" + +# Clean up the pointers +Example::delete_intp(a) +Example::delete_intp(b) +Example::delete_intp(c) + +# Now try the typemap library +# This should be much easier. Now how it is no longer +# necessary to manufacture pointers. + +print "Trying the typemap library\n" +r = Example::sub(37, 42) +print " 37 - 42 = #{r}\n" + +# Now try the version with multiple return values + +print "Testing multiple return values\n" +q, r = Example::divide(42, 37) +print " 42/37 = #{q} remainder #{r}\n" + + + |