diff --git a/Examples/perl5/index.html b/Examples/perl5/index.html index 5c69e06b5..bb346af66 100644 --- a/Examples/perl5/index.html +++ b/Examples/perl5/index.html @@ -17,6 +17,7 @@ be used to wrap a C function and a global variable.
  • constants. This shows how preprocessor macros and certain C declarations are turned into constants.
  • variables. This example shows how to access C global variables from Perl. +
  • value. How to pass and return structures by value.

    Compilation Issues

    diff --git a/Examples/perl5/value/Makefile b/Examples/perl5/value/Makefile new file mode 100644 index 000000000..e5944f9af --- /dev/null +++ b/Examples/perl5/value/Makefile @@ -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 diff --git a/Examples/perl5/value/example.c b/Examples/perl5/value/example.c new file mode 100644 index 000000000..4ed2fe10a --- /dev/null +++ b/Examples/perl5/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/perl5/value/example.h b/Examples/perl5/value/example.h new file mode 100644 index 000000000..212cf4bdb --- /dev/null +++ b/Examples/perl5/value/example.h @@ -0,0 +1,5 @@ +/* File : example.h */ + +typedef struct { + double x, y, z; +} Vector; diff --git a/Examples/perl5/value/example.i b/Examples/perl5/value/example.i new file mode 100644 index 000000000..83c1f9cd6 --- /dev/null +++ b/Examples/perl5/value/example.i @@ -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); +} +%} + diff --git a/Examples/perl5/value/example.pl b/Examples/perl5/value/example.pl new file mode 100644 index 000000000..b640315df --- /dev/null +++ b/Examples/perl5/value/example.pl @@ -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"; + + + + + + diff --git a/Examples/perl5/value/index.html b/Examples/perl5/value/index.html new file mode 100644 index 000000000..ac62a48d5 --- /dev/null +++ b/Examples/perl5/value/index.html @@ -0,0 +1,128 @@ + + +SWIG:Examples:perl5:value + + + + + +SWIG/Examples/perl5/value/ +
    + +

    Passing and Returning Structures by Value

    + +$Header$
    + +

    +Occasionally, a C program will manipulate structures by value such as shown in the +following code: + +

    +
    +/* 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;
    +}
    +
    +
    + +Since SWIG only knows how to manage pointers to structures (not their internal +representation), the following translations are made when wrappers are +created: + +
    +
    +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;
    +}
    +
    +
    + +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). + +

    The SWIG interface

    + +Click here to see a SWIG interface file that +wraps these two functions. In this file, there are a few essential features: + + + +

    A Perl Script

    + +Click here to see a script that uses these functions from Perl. + +

    Notes

    + + + +
    + +