diff options
Diffstat (limited to 'Examples/ruby/value')
-rw-r--r-- | Examples/ruby/value/Makefile | 18 | ||||
-rw-r--r-- | Examples/ruby/value/example.c | 15 | ||||
-rw-r--r-- | Examples/ruby/value/example.h | 5 | ||||
-rw-r--r-- | Examples/ruby/value/example.i | 32 | ||||
-rw-r--r-- | Examples/ruby/value/index.html | 114 | ||||
-rw-r--r-- | Examples/ruby/value/runme.rb | 32 |
6 files changed, 216 insertions, 0 deletions
diff --git a/Examples/ruby/value/Makefile b/Examples/ruby/value/Makefile new file mode 100644 index 0000000..8c4fe10 --- /dev/null +++ b/Examples/ruby/value/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/value/example.c b/Examples/ruby/value/example.c new file mode 100644 index 0000000..4ed2fe1 --- /dev/null +++ b/Examples/ruby/value/example.c @@ -0,0 +1,15 @@ +/* File : example.c */ + +#include "example.h" + +double dot_product(Vector a, Vector b) { + return (a.x*b.x + a.y*b.y + a.z*b.z); +} + +Vector vector_add(Vector a, Vector b) { + Vector r; + r.x = a.x + b.x; + r.y = a.y + b.y; + r.z = a.z + b.z; + return r; +} diff --git a/Examples/ruby/value/example.h b/Examples/ruby/value/example.h new file mode 100644 index 0000000..212cf4b --- /dev/null +++ b/Examples/ruby/value/example.h @@ -0,0 +1,5 @@ +/* File : example.h */ + +typedef struct { + double x, y, z; +} Vector; diff --git a/Examples/ruby/value/example.i b/Examples/ruby/value/example.i new file mode 100644 index 0000000..98fd60e --- /dev/null +++ b/Examples/ruby/value/example.i @@ -0,0 +1,32 @@ +// Tests SWIG's handling of pass-by-value for complex datatypes +%module example + +%{ +#include "example.h" +%} + +/* Some functions that manipulate Vectors by value */ +%inline %{ +extern double dot_product(Vector a, Vector b); +extern Vector vector_add(Vector a, Vector b); +%} + +/* Include this because the vector_add() function will leak memory */ +void free(void *); + +/* Some helper functions for our interface */ +%inline %{ + +Vector *new_Vector(double x, double y, double z) { + Vector *v = (Vector *) malloc(sizeof(Vector)); + v->x = x; + v->y = y; + v->z = z; + return v; +} + +void vector_print(Vector *v) { + printf("Vector %p = (%g, %g, %g)\n", v, v->x, v->y, v->z); +} +%} + diff --git a/Examples/ruby/value/index.html b/Examples/ruby/value/index.html new file mode 100644 index 0000000..cd99ba1 --- /dev/null +++ b/Examples/ruby/value/index.html @@ -0,0 +1,114 @@ +<html> +<head> +<title>SWIG:Examples:ruby:value</title> +</head> + +<body bgcolor="#ffffff"> + + +<tt>SWIG/Examples/ruby/value/</tt> +<hr> + +<H2>Passing and Returning Structures by Value</H2> + +<p> +Occasionally, a C program will manipulate structures by value such as shown in the +following code: + +<blockquote> +<pre> +/* File : example.c */ + +typedef struct Vector { + double x, y, z; +} Vector; + +double dot_product(Vector a, Vector b) { + return (a.x*b.x + a.y*b.y + a.z*b.z); +} + +Vector vector_add(Vector a, Vector b) { + Vector r; + r.x = a.x + b.x; + r.y = a.y + b.y; + r.z = a.z + b.z; + return r; +} +</pre> +</blockquote> + +Since SWIG only knows how to manage pointers to structures (not their internal +representation), the following translations are made when wrappers are +created: + +<blockquote> +<pre> +double wrap_dot_product(Vector *a, Vector *b) { + return dot_product(*a,*b); +} + +Vector *wrap_vector_add(Vector *a, Vector *b) { + Vector *r = (Vector *) malloc(sizeof(Vector)); + *r = vector_add(*a,*b); + return r; +} +</pre> +</blockquote> + +The functions are then called using pointers from the scripting language interface. +It should also be noted that any function that returns a structure by value results +in an implicit memory allocation. This will be a memory leak unless you take steps +to free the result (see below). + +<h2>The SWIG interface</h2> + +Click <a href="example.i">here</a> to see a SWIG interface file that +wraps these two functions. In this file, there are a few essential features: + +<ul> +<li>A wrapper for the <tt>free()</tt> function is created so that we +can clean up the return result created by <tt>vector_add()</tt> +function. + +<p> +<li>The %inline directive is used to create a few helper functions for creating new Vector +objects and to print out the value (for debugging purposes). +</ul> + +<h2>A Ruby Script</h2> + +Click <a href="runme.rb">here</a> to see a script that uses these functions from Ruby. + +<h2>Notes</h2> + +<ul> +<li>When the '<tt>-c++</tt>' option is used, the resulting wrapper code for the return value +changes to the following: + +<blockquote> +<pre> +Vector *wrap_vector_add(Vector *a, Vector *b) { + Vector *r = new Vector(vector_add(*a,*b)); + return r; +} +</pre> +</blockquote> + +<p> +<li>If you define C structure (or C++ class with '<tt>-c++</tt>' option) +in the interface file, the SWIG generated wrappers can automaticallyclean +up the result of return-by-reference by GC. + +<p> +<li>Passing parameters by value like this really isn't the best C programming style. +If possible, you might change your application to use pointers. + +<p> +<li>Similar translations are made when C++ references are used. + + +</ul> + +<hr> +</body> +</html> diff --git a/Examples/ruby/value/runme.rb b/Examples/ruby/value/runme.rb new file mode 100644 index 0000000..9372c03 --- /dev/null +++ b/Examples/ruby/value/runme.rb @@ -0,0 +1,32 @@ +# file: runme.rb + +require 'example' + +# Create a couple of a vectors + +v = Example::new_Vector(1, 2, 3) +w = Example::new_Vector(10, 11, 12) + +print "I just created the following vectors\n" +Example::vector_print(v) +Example::vector_print(w) + +# Now call some of our functions + +print "\nNow I'm going to compute the dot product\n" +d = Example::dot_product(v,w) +print "dot product = #{d} (should be 68)\n" + +# Add the vectors together + +print "\nNow I'm going to add the vectors together\n" +r = Example::vector_add(v,w) +Example::vector_print(r) +print "The value should be (11, 13, 15)\n" + +# Now I'd better clean up the return result r + +print "\nNow I'm going to clean up the return result\n" +Example::free(r) + +print "Good\n" |