New example

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@765 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Dave Beazley 2000-08-31 18:20:37 +00:00
commit 561f2a9b97
7 changed files with 235 additions and 0 deletions

View file

@ -17,6 +17,7 @@ be used to wrap a C function and a global variable.
<li><a href="constants/index.html">constants</a>. This shows how preprocessor macros and
certain C declarations are turned into constants.
<li><a href="variables/index.html">variables</a>. This example shows how to access C global variables from Perl.
<li><a href="value/index.html">value</a>. How to pass and return structures by value.
</ul>
<h2>Compilation Issues</h2>

View file

@ -0,0 +1,18 @@
TOP = ../..
SWIG = $(TOP)/../swig
SRCS = example.c
TARGET = example
INTERFACE = example.i
SWIGOPT =
all::
$(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \
SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' perl5
static::
$(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \
SWIGOPT='$(SWIGOPT)' TARGET='myperl' INTERFACE='$(INTERFACE)' perl5_static
clean::
rm -f *_wrap* *.o core *~ *.so *.pm myperl
check: all

View file

@ -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;
}

View file

@ -0,0 +1,5 @@
/* File : example.h */
typedef struct {
double x, y, z;
} Vector;

View file

@ -0,0 +1,30 @@
// Tests SWIG's handling of pass-by-value for complex datatypes
%module example
%{
#include "example.h"
%}
/* Some functions that manipulate Vectors by value */
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 %x = (%g, %g, %g)\n", v, v->x, v->y, v->z);
}
%}

View file

@ -0,0 +1,38 @@
# file: example.pl
use 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";

View file

@ -0,0 +1,128 @@
<html>
<head>
<title>SWIG:Examples:perl5:value</title>
</head>
<body bgcolor="#ffffff">
<tt>SWIG/Examples/perl5/value/</tt>
<hr>
<H2>Passing and Returning Structures by Value</H2>
<tt>$Header$</tt><br>
<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 Perl Script</h2>
Click <a href="example.pl">here</a> to see a script that uses these functions from Perl.
<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>
Similarly, it would be a mistake to use the <tt>free()</tt> function from C++. A safer
approach would be to write a helper function like this:
<blockquote>
<pre>
%inline %{
void delete_Vector(Vector *v) {
delete v;
}
%}
</pre>
</blockquote>
<p>
<li>If you use shadow classes and are careful, the SWIG generated wrappers can automatically
clean up the result of return-by-reference when the scripting variable goes out of scope.
<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>