| 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> |