Changeset 43
- Timestamp:
- 10/27/06 01:05:57 (2 years ago)
- Files:
-
- trunk/html_doc/class_wrapping.html (modified) (2 diffs)
- trunk/infrastructure/pyd/op_wrap.d (modified) (8 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/html_doc/class_wrapping.html
r42 r43 53 53 <dd>This allows the user to specify a different overload of opApply than the default. (The default is always the one that is lexically first.) The <span class="t_arg">iter_t</span> argument should be the type of the delegate that forms the argument to opApply. This might be e.g. <code>int delegate(inout int)</code>. Don't forget the <code>inout</code> modifiers!</dd> 54 54 55 <dt><code>static void alt_iter(alias <span class="t_arg">fn</span>, char[] <span class="t_arg">name</span> = symbolnameof!(fn), iter_t= <i>implementationDetail</i>) ();</code></dt>55 <dt><code>static void alt_iter(alias <span class="t_arg">fn</span>, char[] <span class="t_arg">name</span> = symbolnameof!(fn), <span class="t_arg">iter_t</span> = <i>implementationDetail</i>) ();</code></dt> 56 56 <dd>This wraps alternate iterator methods as Python methods that return iterator objects. The wrapped methods should have a signature like that of opApply. (In other words, they should be methods intended to be used with D's ability to iterate over delgates.) The <span class="t_arg">iter_t</span> argument should be the type of the delegate argument to the method. This will usually be derived automatically. 57 57 </dd> … … 81 81 <p>At the moment, only the following operator overloads are supported:</p> 82 82 83 <p><code>opAdd, opSub, opMul, opDiv, opMod, opAnd, opOr, opXor, opShl, opShr, opCat, opAddAssign, opSubAssign, opMulAssign, opDivAssign, opModAssign, opAndAssign, opOrAssign, opXorAssign, opShlAssign, opShrAssign, opCatAssign, opIn_r, opCmp, opCall, opApply </code></p>83 <p><code>opAdd, opSub, opMul, opDiv, opMod, opAnd, opOr, opXor, opShl, opShr, opCat, opAddAssign, opSubAssign, opMulAssign, opDivAssign, opModAssign, opAndAssign, opOrAssign, opXorAssign, opShlAssign, opShrAssign, opCatAssign, opIn_r, opCmp, opCall, opApply, opIndex, opIndexAssign, opSlice, opSliceAssign</code></p> 84 84 85 <p>M ost notably missing from this list are <code>opIndex, opIndexAssign, opSlice</code>, and <code>opSliceAssign</code>. Support for these operators is forthcoming. Also missing from the list are <code>opUShr</code> and <code>opUShrAssign</code>. Python does not have an unsigned right-shift operator, so these operator overloads are not supported. (You may still wrap them with a normal method using <code>wrapped_class.def</code>, of course.) Also missing from the list is <code>opApplyReverse</code>. This must be wrapped explicitly with <code>alt_iter</code>.</p>85 <p>Missing from this list are <code>opUShr</code> and <code>opUShrAssign</code>. Python does not have an unsigned right-shift operator, so these operator overloads are not supported. (You may still wrap them with a normal method using <code>wrapped_class.def</code>, of course.) Also missing from the list is <code>opApplyReverse</code>. This must be wrapped explicitly with <code>wrapped_class.alt_iter</code>.</p> 86 86 87 87 <!-- This is not yet implemented. 88 <p>Additionally, if a class provides a <code>length</code> property, Pyd will automatically make it available via Python's built-in function <code>len</code>. You may still wrap it with <code>prop</code> if you wish it to be available as a normal property.</p>88 <p>Additionally, if a class provides a <code>length</code> property, Pyd will automatically make it available via Python's built-in function <code>len</code>. You may still wrap it with <code>prop</code> or <code>def</code> if you wish it to be available as a normal property or method.</p> 89 89 --> 90 90 91 <p>Notably <em>included</em> in the list is <code>opApply</code>. Pyd wraps D's iteration protocol with the help of Mikola Lysenko's StackThreads package.</p> 91 <p><b>Notes on wrapped operators</b></p> 92 93 <dl> 94 <dt><code>opApply</code></dt> <dd>Pyd wraps D's iteration protocol with the help of Mikola Lysenko's StackThreads package.</dd> 95 <dt><code>opIndex, opIndexAssign</code></dt> <dd>Pyd only supports these overloads if they have precisely one index argument. This is a limitation of the Python/C API.</dd> 96 <dt><code>opSlice, opSliceAssign</code></dt> <dd>Pyd only supports these overloads if both of their two indexes are implicitly convertable to type <code>int</code>. This is a limitation of the Python/C API.</dd> 97 <dt><code>opCat, opCatAssign</code></dt> <dd>Python does not have a dedicated array concatenation operator. The plus sign (<code>+</code>) is reused for this purpose. Therefore, odd behavior may result with classes that define both <code>opAdd/opAddAssign</code> and one or both of these operators. (Consider yourself warned.) However, the Python/C API considers addition and concatenation distinct operations, and so both of these sets of operator overloads are supported.</dd> 98 <dt><code>opIn_r</code></dt> <dd>Python expects the <code>in</code> operator to return a boolean value (it is a containment test). D convention is for <code>in</code> to search for the value in the container, and to return a pointer to the found item, or <code>null</code> if the item is not found. That said, D does not enforce any particular signature on the <code>in</code> overload, while the Python/C API does. Pyd will check the boolean result of a call to <code>opIn_r</code>, and return that value to Python.</dd> 99 </dl> 92 100 93 101 <h3><a class="anchor" name="examples">Examples</a></h3> trunk/infrastructure/pyd/op_wrap.d
r41 r43 25 25 26 26 private import pyd.class_wrap; 27 private import pyd.dg_convert; 27 28 private import pyd.func_wrap; 28 29 private import pyd.exception; … … 76 77 template wrapped_class_as_sequence(T) { 77 78 static PySequenceMethods wrapped_class_as_sequence = { 78 null, /*sq_length*/79 opCat_wrap!(T), /*sq_concat*/80 null, /*sq_repeat*/81 null,/*sq_item*/82 null,/*sq_slice*/83 null,/*sq_ass_item*/84 null,/*sq_ass_slice*/85 null, /*sq_contains*/86 opCatAssign_wrap!(T), /*sq_inplace_concat*/87 null, /*sq_inplace_repeat*/79 null, /*sq_length*/ 80 opCat_wrap!(T), /*sq_concat*/ 81 null, /*sq_repeat*/ 82 opIndex_sequence_wrap!(T), /*sq_item*/ 83 opSlice_wrap!(T), /*sq_slice*/ 84 opIndexAssign_sequence_wrap!(T), /*sq_ass_item*/ 85 opSliceAssign_wrap!(T), /*sq_ass_slice*/ 86 null, /*sq_contains*/ 87 opCatAssign_wrap!(T), /*sq_inplace_concat*/ 88 null, /*sq_inplace_repeat*/ 88 89 }; 89 90 } … … 91 92 template wrapped_class_as_mapping(T) { 92 93 static PyMappingMethods wrapped_class_as_mapping = { 93 null, /*mp_length*/94 null,/*mp_subscript*/95 null,/*mp_ass_subscript*/94 null, /*mp_length*/ 95 opIndex_mapping_wrap!(T), /*mp_subscript*/ 96 opIndexAssign_mapping_wrap!(T), /*mp_ass_subscript*/ 96 97 }; 97 98 } … … 99 100 template opfunc_binary_wrap(T, alias opfn) { 100 101 alias wrapped_class_object!(T) wrap_object; 102 alias funcDelegInfoT!(typeof(&opfn)) Info; 101 103 extern(C) 102 104 PyObject* func(PyObject* self, PyObject* o) { 103 PyObject* temp_tuple = PyTuple_New(1); 104 if (temp_tuple is null) return null; 105 Py_INCREF(o); 106 PyTuple_SetItem(temp_tuple, 0, o); 107 PyObject* res = func_wrap!(opfn, 1, T).func(self, temp_tuple); 108 Py_DECREF(temp_tuple); 109 return res; 105 return exception_catcher(delegate PyObject*() { 106 auto dg = dg_wrapper((cast(wrap_object*)self).d_obj, &opfn); 107 return _py(dg(d_type!(Info.Meta.ArgType!(0))(o))); 108 }); 110 109 } 111 110 } 112 111 113 112 template opfunc_unary_wrap(T, alias opfn) { 114 alias wrapped_class_object!(T) wrap_object;115 113 extern(C) 116 114 PyObject* func(PyObject* self) { 115 // func_wrap takes care of exception handling 117 116 return func_wrap!(opfn, 0, T).func(self, null); 118 117 } … … 132 131 template opindexassign_sequence_pyfunc(T) { 133 132 alias wrapped_class_object!(T) wrap_object; 133 alias funcDelegInfoT!(typeof(&T.opIndexAssign)) Info; 134 alias Info.Meta.ArgType!(0) AssignT; 134 135 135 136 extern(C) 136 137 int func(PyObject* self, int i, PyObject* o) { 137 138 return exception_catcher(delegate int() { 139 (cast(wrap_object*)self).d_obj.opIndexAssign(d_type!(AssignT)(o), i); 140 return 0; 141 }); 142 } 143 } 144 145 template opindexassign_mapping_pyfunc(T) { 146 alias wrapped_class_object!(T) wrap_object; 147 alias funcDelegInfoT!(typeof(&T.opIndexAssign)) Info; 148 alias Info.Meta.ArgType!(0) ValT; 149 alias Info.Meta.ArgType!(1) KeyT; 150 151 extern(C) 152 int func(PyObject* self, PyObject* key, PyObject* val) { 153 return exception_catcher(delegate int() { 154 (cast(wrap_object*)self).d_obj.opIndexAssign(d_type!(ValT)(val), d_type!(KeyT)(key)); 155 return 0; 156 }); 157 } 158 } 159 160 template opslice_pyfunc(T) { 161 alias wrapped_class_object!(T) wrap_object; 162 163 extern(C) 164 PyObject* func(PyObject* self, int i1, int i2) { 165 return exception_catcher(delegate PyObject*() { 166 return _py((cast(wrap_object*)self).d_obj.opSlice(i1, i2)); 167 }); 168 } 169 } 170 171 template opsliceassign_pyfunc(T) { 172 alias wrapped_class_object!(T) wrap_object; 173 alias funcDelegInfoT!(typeof(&T.opSliceAssign)) Info; 174 alias Info.Meta.ArgType!(0) AssignT; 175 176 extern(C) 177 int func(PyObject* self, int i1, int i2, PyObject* o) { 178 return exception_catcher(delegate int() { 179 (cast(wrap_object*)self).d_obj.opSliceAssign(d_type!(AssignT)(o), i1, i2); 180 return 0; 181 }); 182 } 183 } 184 185 template opin_wrap(T) { 186 alias wrapped_class_object!(T) wrap_object; 187 alias funcDelegInfoT!(typeof(&T.opIn_r)) Info; 188 alias Info.Meta.ArgType!(0) OtherT; 189 190 extern(C) 191 int func(PyObject* self, PyObject* val) { 192 return exception_catcher(delegate int() { 193 if ((cast(wrap_object*)self).d_obj.opIn_r(d_type!(OtherT)(val))) 194 return 1; 195 else 196 return 0; 197 }); 138 198 } 139 199 } … … 159 219 // The rest of the file is composed of these short stubs 160 220 template opIndex_sequence_wrap(T) { 161 static if (is(typeof(&T.opIndex)) && 162 funcDelegInfoT!(typeof(&T.opIndex)).numArgs == 1 && 163 is(funcDelegInfoT!(typeof(&T.opIndex)).Meta.ArgType!(0) : int) 221 static if ( 222 is(typeof(&T.opIndex)) && 223 funcDelegInfoT!(typeof(&T.opIndex)).numArgs == 1 && 224 is(funcDelegInfoT!(typeof(&T.opIndex)).Meta.ArgType!(0) : int) 164 225 ) { 165 226 const intargfunc opIndex_sequence_wrap = &opindex_sequence_pyfunc!(T).func; … … 170 231 171 232 template opIndexAssign_sequence_wrap(T) { 172 static if (true) { 233 static if ( 234 is(typeof(&T.opIndexAssign)) && 235 funcDelegInfoT!(typeof(&T.opIndexAssign)).numArgs == 2 && 236 is(funcDelegInfoT!(typeof(&T.opIndexAssign)).Meta.ArgType!(1) : int) 237 ) { 238 const intobjargproc opIndexAssign_sequence_wrap = &opindexassign_sequence_pyfunc!(T).func; 239 } else { 173 240 const intobjargproc opIndexAssign_sequence_wrap = null; 174 } else {175 const intobjargproc opIndexAssign_sequence_wrap = null;176 241 } 177 242 } 178 243 179 244 template opIndex_mapping_wrap(T) { 180 245 static if ( 246 is(typeof(&T.opIndex)) && 247 funcDelegInfoT!(typeof(&T.opIndex)).numArgs == 1 && 248 !is(funcDelegInfoT!(typeof(&T.opIndex)).Meta.ArgType!(0) : int) 249 ) { 250 const binaryfunc opIndex_mapping_wrap = &opfunc_binary_wrap!(T, T.opIndex).func; 251 } else { 252 const binaryfunc opIndex_mapping_wrap = null; 253 } 181 254 } 182 255 183 256 template opIndexAssign_mapping_wrap(T) { 184 257 static if ( 258 is(typeof(&T.opIndexAssign)) && 259 funcDelegInfoT!(typeof(&T.opIndexAssign)).numArgs == 2 && 260 !is(funcDelegInfoT!(typeof(&T.opIndexAssign)).Meta.ArgType!(1) : int) 261 ) { 262 const objobjargproc opIndexAssign_mapping_wrap = &opindexassign_mapping_pyfunc!(T).func; 263 } else { 264 const objobjargproc opIndexAssign_mapping_wrap = null; 265 } 185 266 } 186 267 187 268 template opSlice_wrap(T) { 188 269 static if ( 270 is(typeof(&T.opSlice)) && 271 funcDelegInfoT!(typeof(&T.opSlice)).numArgs == 2 && 272 is(funcDelegInfoT!(typeof(&T.opSlice)).Meta.ArgType!(0) : int) && 273 is(funcDelegInfoT!(typeof(&T.opSlice)).Meta.ArgType!(1) : int) 274 ) { 275 const intintargfunc opSlice_wrap = opslice_pyfunc!(T).func; 276 } else { 277 const intintargfunc opSlice_wrap = null; 278 } 189 279 } 190 280 191 281 template opSliceAssign_wrap(T) { 192 282 static if ( 283 is(typeof(&T.opSlice)) && 284 funcDelegInfoT!(typeof(&T.opSlice)).numArgs == 3 && 285 is(funcDelegInfoT!(typeof(&T.opSlice)).Meta.ArgType!(1) : int) && 286 is(funcDelegInfoT!(typeof(&T.opSlice)).Meta.ArgType!(2) : int) 287 ) { 288 const intintobjargproc opSliceAssign_wrap = opsliceassign_pyfunc!(T).func; 289 } else { 290 const intintobjargproc opSliceAssign_wrap = null; 291 } 193 292 } 194 293 … … 410 509 template opIn_wrap(T) { 411 510 static if (is(typeof(&T.opIn_r))) { 412 const binaryfunc opIn_wrap = &op func_binary_wrap!(T, T.opIn_r).func;511 const binaryfunc opIn_wrap = &opin_wrap.func; 413 512 } else { 414 513 const binaryfunc opIn_wrap = null;
