| <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> |
| |
| <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="runme.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> |