<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> <tt>$Header: /cvs/projects/SWIG/Examples/ruby/value/index.html,v 1.1 2000/09/18 13:21:27 fukusima Exp $</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 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>