Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> |
2 | <html> | |
3 | <head> | |
4 | <title>Contract Checking</title> | |
5 | <link rel="stylesheet" type="text/css" href="style.css"> | |
6 | </head> | |
7 | ||
8 | <body bgcolor="#ffffff"> | |
9 | <H1><a name="Contract"></a>12 Contracts</H1> | |
10 | <!-- INDEX --> | |
11 | <div class="sectiontoc"> | |
12 | <ul> | |
13 | <li><a href="#Contract_nn2">The %contract directive</a> | |
14 | <li><a href="#Contract_nn3">%contract and classes</a> | |
15 | <li><a href="#Contract_nn4">Constant aggregation and %aggregate_check</a> | |
16 | <li><a href="#Contract_nn5">Notes</a> | |
17 | </ul> | |
18 | </div> | |
19 | <!-- INDEX --> | |
20 | ||
21 | ||
22 | ||
23 | <p> | |
24 | A common problem that arises when wrapping C libraries is that of maintaining | |
25 | reliability and checking for errors. The fact of the matter is that many | |
26 | C programs are notorious for not providing error checks. Not only that, | |
27 | when you expose the internals of an application as a library, it | |
28 | often becomes possible to crash it simply by providing bad inputs or | |
29 | using it in a way that wasn't intended. | |
30 | </p> | |
31 | ||
32 | <p> | |
33 | This chapter describes SWIG's support for software contracts. In the context | |
34 | of SWIG, a contract can be viewed as a runtime constraint that is attached | |
35 | to a declaration. For example, you can easily attach argument checking rules, | |
36 | check the output values of a function and more. | |
37 | When one of the rules is violated by a script, a runtime exception is | |
38 | generated rather than having the program continue to execute. | |
39 | </p> | |
40 | ||
41 | <H2><a name="Contract_nn2"></a>12.1 The %contract directive</H2> | |
42 | ||
43 | ||
44 | <p> | |
45 | Contracts are added to a declaration using the %contract directive. Here | |
46 | is a simple example: | |
47 | </p> | |
48 | ||
49 | <div class="code"> | |
50 | <pre> | |
51 | %contract sqrt(double x) { | |
52 | require: | |
53 | x >= 0; | |
54 | ensure: | |
55 | sqrt >= 0; | |
56 | } | |
57 | ||
58 | ... | |
59 | double sqrt(double); | |
60 | </pre> | |
61 | </div> | |
62 | ||
63 | <p> | |
64 | In this case, a contract is being added to the <tt>sqrt()</tt> function. | |
65 | The <tt>%contract</tt> directive must always appear before the declaration | |
66 | in question. Within the contract there are two sections, both of which | |
67 | are optional. The <tt>require:</tt> | |
68 | section specifies conditions that must hold before the function is called. | |
69 | Typically, this is used to check argument values. The <tt>ensure:</tt> section | |
70 | specifies conditions that must hold after the function is called. This is | |
71 | often used to check return values or the state of the program. In both | |
72 | cases, the conditions that must hold must be specified as boolean expressions. | |
73 | </p> | |
74 | ||
75 | <p> | |
76 | In the above example, we're simply making sure that sqrt() returns a non-negative | |
77 | number (if it didn't, then it would be broken in some way). | |
78 | </p> | |
79 | ||
80 | <p> | |
81 | Once a contract has been specified, it modifies the behavior of the | |
82 | resulting module. For example: | |
83 | </p> | |
84 | ||
85 | <div class="shell"> | |
86 | <pre> | |
87 | >>> example.sqrt(2) | |
88 | 1.4142135623730951 | |
89 | >>> example.sqrt(-2) | |
90 | Traceback (most recent call last): | |
91 | File "<stdin>", line 1, in ? | |
92 | RuntimeError: Contract violation: require: (arg1>=0) | |
93 | >>> | |
94 | </pre> | |
95 | </div> | |
96 | ||
97 | <H2><a name="Contract_nn3"></a>12.2 %contract and classes</H2> | |
98 | ||
99 | ||
100 | <p> | |
101 | The <tt>%contract</tt> directive can also be applied to class methods and constructors. For example: | |
102 | </p> | |
103 | ||
104 | <div class="code"> | |
105 | <pre> | |
106 | %contract Foo::bar(int x, int y) { | |
107 | require: | |
108 | x > 0; | |
109 | ensure: | |
110 | bar > 0; | |
111 | } | |
112 | ||
113 | %contract Foo::Foo(int a) { | |
114 | require: | |
115 | a > 0; | |
116 | } | |
117 | ||
118 | class Foo { | |
119 | public: | |
120 | Foo(int); | |
121 | int bar(int, int); | |
122 | }; | |
123 | </pre> | |
124 | </div> | |
125 | ||
126 | <p> | |
127 | The way in which <tt>%contract</tt> is applied is exactly the same as the <tt>%feature</tt> directive. | |
128 | Thus, any contract that you specified for a base class will also be attached to inherited methods. For example: | |
129 | </p> | |
130 | ||
131 | <div class="code"> | |
132 | <pre> | |
133 | class Spam : public Foo { | |
134 | public: | |
135 | int bar(int,int); // Gets contract defined for Foo::bar(int,int) | |
136 | }; | |
137 | </pre> | |
138 | </div> | |
139 | ||
140 | <p> | |
141 | In addition to this, separate contracts can be applied to both the base class and a derived class. For example: | |
142 | </p> | |
143 | ||
144 | <div class="code"> | |
145 | <pre> | |
146 | %contract Foo::bar(int x, int) { | |
147 | require: | |
148 | x > 0; | |
149 | } | |
150 | ||
151 | %contract Spam::bar(int, int y) { | |
152 | require: | |
153 | y > 0; | |
154 | } | |
155 | ||
156 | class Foo { | |
157 | public: | |
158 | int bar(int,int); // Gets Foo::bar contract. | |
159 | }; | |
160 | ||
161 | class Spam : public Foo { | |
162 | public: | |
163 | int bar(int,int); // Gets Foo::bar and Spam::bar contract | |
164 | }; | |
165 | </pre> | |
166 | </div> | |
167 | ||
168 | <p> | |
169 | When more than one contract is applied, the conditions specified in a | |
170 | "require:" section are combined together using a logical-AND operation. | |
171 | In other words conditions specified for the base class and conditions | |
172 | specified for the derived class all must hold. In the above example, | |
173 | this means that both the arguments to <tt>Spam::bar</tt> must be positive. | |
174 | </p> | |
175 | ||
176 | <H2><a name="Contract_nn4"></a>12.3 Constant aggregation and %aggregate_check</H2> | |
177 | ||
178 | ||
179 | <p> | |
180 | Consider an interface file that contains the following code: | |
181 | </p> | |
182 | ||
183 | <div class="code"> | |
184 | <pre> | |
185 | #define UP 1 | |
186 | #define DOWN 2 | |
187 | #define RIGHT 3 | |
188 | #define LEFT 4 | |
189 | ||
190 | void move(SomeObject *, int direction, int distance); | |
191 | </pre> | |
192 | </div> | |
193 | ||
194 | <p> | |
195 | One thing you might want to do is impose a constraint on the direction parameter to | |
196 | make sure it's one of a few accepted values. To do that, SWIG provides an easy to | |
197 | use macro %aggregate_check() that works like this: | |
198 | </p> | |
199 | ||
200 | <div class="code"> | |
201 | <pre> | |
202 | %aggregate_check(int, check_direction, UP, DOWN, LEFT, RIGHT); | |
203 | </pre> | |
204 | </div> | |
205 | ||
206 | <p> | |
207 | This merely defines a utility function of the form | |
208 | </p> | |
209 | ||
210 | <div class="code"> | |
211 | <pre> | |
212 | int check_direction(int x); | |
213 | </pre> | |
214 | </div> | |
215 | ||
216 | <p> | |
217 | That checks the argument x to see if it is one of the values listed. This utility | |
218 | function can be used in contracts. For example: | |
219 | </p> | |
220 | ||
221 | <div class="code"> | |
222 | <pre> | |
223 | %aggregate_check(int, check_direction, UP, DOWN, RIGHT, LEFT); | |
224 | ||
225 | %contract move(SomeObject *, int direction, in) { | |
226 | require: | |
227 | check_direction(direction); | |
228 | } | |
229 | ||
230 | #define UP 1 | |
231 | #define DOWN 2 | |
232 | #define RIGHT 3 | |
233 | #define LEFT 4 | |
234 | ||
235 | void move(SomeObject *, int direction, int distance); | |
236 | </pre> | |
237 | </div> | |
238 | ||
239 | <p> | |
240 | Alternatively, it can be used in typemaps and other directives. For example: | |
241 | </p> | |
242 | ||
243 | <div class="code"> | |
244 | <pre> | |
245 | %aggregate_check(int, check_direction, UP, DOWN, RIGHT, LEFT); | |
246 | ||
247 | %typemap(check) int direction { | |
248 | if (!check_direction($1)) SWIG_exception(SWIG_ValueError, "Bad direction"); | |
249 | } | |
250 | ||
251 | #define UP 1 | |
252 | #define DOWN 2 | |
253 | #define RIGHT 3 | |
254 | #define LEFT 4 | |
255 | ||
256 | void move(SomeObject *, int direction, int distance); | |
257 | </pre> | |
258 | </div> | |
259 | ||
260 | <p> | |
261 | Regrettably, there is no automatic way to perform similar checks with enums values. Maybe in a future | |
262 | release. | |
263 | </p> | |
264 | ||
265 | <H2><a name="Contract_nn5"></a>12.4 Notes</H2> | |
266 | ||
267 | ||
268 | <p> | |
269 | Contract support was implemented by Songyan (Tiger) Feng and first appeared | |
270 | in SWIG-1.3.20. | |
271 | </p> | |
272 | ||
273 | </body> | |
274 | </html> |