aboutsummaryrefslogtreecommitdiff
path: root/Examples/perl5/value/index.html
blob: 0e9502a0095e58cd50b650237f01e547e45ef167 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
<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>

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