New example
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@762 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
parent
877aa52016
commit
794ff1ed6c
8 changed files with 235 additions and 2 deletions
|
|
@ -17,7 +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>. How SWIG can be used to wrap C global variables.
|
||||
|
||||
<li><a href="value/index.html">value</a>. How to pass and return structures by value.
|
||||
</ul>
|
||||
|
||||
<h2>Compilation Issues</h2>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# file: example.tcl
|
||||
# Try to load as a dynamic module. If not, we'll just assume
|
||||
# Try to load as a dynamic module.
|
||||
|
||||
catch { load ./example.so example}
|
||||
catch { load ./example.dll example} ;# Windows
|
||||
|
|
|
|||
19
Examples/tcl/value/Makefile
Normal file
19
Examples/tcl/value/Makefile
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
TOP = ../..
|
||||
SWIG = $(TOP)/../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::
|
||||
rm -f *_wrap* *.o my_tclsh *~ .~* core *.so *.sl
|
||||
|
||||
check: all
|
||||
15
Examples/tcl/value/example.c
Normal file
15
Examples/tcl/value/example.c
Normal 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;
|
||||
}
|
||||
5
Examples/tcl/value/example.h
Normal file
5
Examples/tcl/value/example.h
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
/* File : example.h */
|
||||
|
||||
typedef struct {
|
||||
double x, y, z;
|
||||
} Vector;
|
||||
30
Examples/tcl/value/example.i
Normal file
30
Examples/tcl/value/example.i
Normal 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);
|
||||
}
|
||||
%}
|
||||
|
||||
40
Examples/tcl/value/example.tcl
Normal file
40
Examples/tcl/value/example.tcl
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
# file: example.py
|
||||
# Try to load as a dynamic module.
|
||||
|
||||
catch { load ./example.so example}
|
||||
catch { load ./example.dll example} ;# Windows
|
||||
|
||||
# Create a couple of a vectors
|
||||
|
||||
set v [new_Vector 1 2 3]
|
||||
set w [new_Vector 10 11 12]
|
||||
|
||||
puts "I just created the following vectors"
|
||||
vector_print $v
|
||||
vector_print $w
|
||||
|
||||
# Now call some of our functions
|
||||
|
||||
puts "\nNow I'm going to compute the dot product"
|
||||
set d [dot_product $v $w]
|
||||
puts "dot product = $d (should be 68)"
|
||||
|
||||
# Add the vectors together
|
||||
|
||||
puts "\nNow I'm going to add the vectors together"
|
||||
set r [vector_add $v $w]
|
||||
vector_print $r
|
||||
puts "The value should be (11,13,15)"
|
||||
|
||||
# Now I'd better clean up the return result r
|
||||
|
||||
puts "\nNow I'm going to clean up the return result"
|
||||
free $r
|
||||
|
||||
puts "Good"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
124
Examples/tcl/value/index.html
Normal file
124
Examples/tcl/value/index.html
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>SWIG:Examples:tcl:value</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#ffffff">
|
||||
|
||||
|
||||
<tt>SWIG/Examples/tcl/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 Tcl Script</h2>
|
||||
|
||||
Click <a href="example.tcl">here</a> to see a script that uses these functions from Tcl.
|
||||
|
||||
<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>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>
|
||||
Loading…
Add table
Add a link
Reference in a new issue