Changeset 50
- Timestamp:
- 12/02/06 20:07:54 (2 years ago)
- Files:
-
- trunk/infrastructure/pyd/class_wrap.d (modified) (5 diffs)
- trunk/infrastructure/pyd/ctor_wrap.d (modified) (1 diff)
- trunk/infrastructure/pyd/def.d (modified) (1 diff)
- trunk/infrastructure/pyd/func_wrap.d (modified) (3 diffs)
- trunk/infrastructure/pyd/make_object.d (modified) (2 diffs)
- trunk/infrastructure/pyd/op_wrap.d (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/infrastructure/pyd/class_wrap.d
r49 r50 214 214 extern(C) 215 215 PyObject* func(PyObject* self, void* closure) { 216 // func_wrap already catches exceptions217 return func_wrap!(Fn, 0, T, property_parts!(Fn).getter_type).func(self, null);216 // method_wrap already catches exceptions 217 return method_wrap!(T, Fn, property_parts!(Fn).getter_type).func(self, null); 218 218 } 219 219 } … … 229 229 Py_INCREF(value); 230 230 PyTuple_SetItem(temp_tuple, 0, value); 231 PyObject* res = func_wrap!(Fn, 1, T, property_parts!(Fn).setter_type).func(self, temp_tuple);231 PyObject* res = method_wrap!(T, Fn, property_parts!(Fn).setter_type).func(self, temp_tuple); 232 232 // If we get something back, we need to DECREF it. 233 233 if (res) Py_DECREF(res); … … 262 262 * if more than one function has the same name as this one. 263 263 */ 264 template def(alias fn, char[] name = symbolnameof!(fn), fn_t=typeof(&fn) , uint MIN_ARGS = minArgs!(fn, fn_t)) {264 template def(alias fn, char[] name = symbolnameof!(fn), fn_t=typeof(&fn)) { 265 265 pragma(msg, "class.def: " ~ name); 266 266 static void def() { … … 268 268 alias wrapped_method_list!(T) list; 269 269 list[length-1].ml_name = name ~ \0; 270 list[length-1].ml_meth = & func_wrap!(fn, MIN_ARGS, T, fn_t).func;270 list[length-1].ml_meth = &method_wrap!(T, fn, fn_t).func; 271 271 list[length-1].ml_flags = METH_VARARGS; 272 272 list[length-1].ml_doc = ""; … … 413 413 // opCall 414 414 static if (is(typeof(&T.opCall))) { 415 type.tp_call = cast(ternaryfunc)& func_wrap!(T.opCall, minArgs!(T.opCall), T).func;415 type.tp_call = cast(ternaryfunc)&method_wrap!(T, T.opCall, typeof(&T.opCall)).func; 416 416 } 417 417 trunk/infrastructure/pyd/ctor_wrap.d
r45 r50 69 69 alias ParameterTypeTuple!(typeof(arg)) Ctor; 70 70 if (Ctor.length == len) { 71 alias call_ctor!(T, ParameterTypeTuple!(typeof(arg))) fn; 72 WrapPyObject_SetObj(self, py_call(&fn, args)); 71 auto fn = &call_ctor!(T, ParameterTypeTuple!(typeof(arg))); 72 if (fn is null) { 73 PyErr_SetString(PyExc_RuntimeError, "Couldn't get pointer to class ctor redirect."); 74 return -1; 75 } 76 T t = applyPyTupleToDelegate(fn, args); 77 if (t is null) { 78 PyErr_SetString(PyExc_RuntimeError, "Class ctor redirect didn't return a class instance!"); 79 return -1; 80 } 81 WrapPyObject_SetObj(self, t); 73 82 return 0; 74 83 } trunk/infrastructure/pyd/def.d
r49 r50 80 80 81 81 list[length-1].ml_name = name ~ \0; 82 list[length-1].ml_meth = &func _wrap!(fn, MIN_ARGS, void, fn_t).func;82 list[length-1].ml_meth = &function_wrap!(fn, MIN_ARGS, fn_t).func; 83 83 list[length-1].ml_flags = METH_VARARGS; 84 84 list[length-1].ml_doc = ""; trunk/infrastructure/pyd/func_wrap.d
r49 r50 35 35 import std.string; 36 36 import std.traits; 37 } 38 39 // Builds a Python callable object from a delegate or function pointer. 37 import std.stdio; 38 } 39 40 // Builds a callable Python object from a delegate or function pointer. 40 41 PyObject* PydFunc_FromDelegate(T) (T dg) { 41 42 alias wrapped_class_type!(T) type; … … 91 92 } 92 93 93 // Calls the passed function with the passed Python tuple.94 ReturnType!(fn_t) py_call(fn_t, PY)(fn_t fn, PY* args) {94 // Calls callable alias fn with PyTuple args. 95 ReturnType!(fn_t) applyPyTupleToAlias(alias fn, fn_t, uint MIN_ARGS) (PyObject* args) { 95 96 alias ParameterTypeTuple!(fn_t) T; 96 97 const uint MAX_ARGS = T.length; 97 98 alias ReturnType!(fn_t) RT; 98 99 99 int ARGS= 0;100 int argCount = 0; 100 101 // This can make it more convenient to call this with 0 args. 101 102 if (args !is null) { 102 ARGS= PyObject_Length(args);103 argCount = PyObject_Length(args); 103 104 } 104 105 105 106 // Sanity check! 106 if ( ARGS !=MAX_ARGS) {107 setWrongArgsError( ARGS, MAX_ARGS, MAX_ARGS);107 if (argCount < MIN_ARGS || argCount > MAX_ARGS) { 108 setWrongArgsError(argCount, MIN_ARGS, MAX_ARGS); 108 109 handle_exception(); 109 110 } 110 111 112 static if (MIN_ARGS == 0) { 113 if (argCount == 0) { 114 return fn(); 115 } 116 } 117 T t; 118 foreach(i, arg; t) { 119 const uint argNum = i+1; 120 if (i < argCount) { 121 t[i] = d_type!(typeof(arg))(PyTuple_GetItem(args, i)); 122 } 123 static if (argNum >= MIN_ARGS && argNum <= MAX_ARGS) { 124 if (argNum == argCount) { 125 return fn(t[0 .. argNum]); 126 break; 127 } 128 } 129 } 130 // This should never get here. 131 throw new Exception("applyPyTupleToAlias reached end! argCount = " ~ toString(argCount)); 132 static if (!is(RT == void)) 133 return ReturnType!(fn_t).init; 134 } 135 136 // wraps applyPyTupleToAlias to return a PyObject* 137 PyObject* pyApplyToAlias(alias fn, fn_t, uint MIN_ARGS) (PyObject* args) { 138 static if (is(ReturnType!(fn_t) == void)) { 139 applyPyTupleToAlias!(fn, fn_t, MIN_ARGS)(args); 140 Py_INCREF(Py_None); 141 return Py_None; 142 } else { 143 return _py( applyPyTupleToAlias!(fn, fn_t, MIN_ARGS)(args) ); 144 } 145 } 146 147 ReturnType!(dg_t) applyPyTupleToDelegate(dg_t) (dg_t dg, PyObject* args) { 148 alias ParameterTypeTuple!(dg_t) T; 149 const uint ARGS = T.length; 150 alias ReturnType!(dg_t) RT; 151 152 int argCount = 0; 153 // This can make it more convenient to call this with 0 args. 154 if (args !is null) { 155 argCount = PyObject_Length(args); 156 } 157 158 // Sanity check! 159 if (argCount != ARGS) { 160 setWrongArgsError(argCount, ARGS, ARGS); 161 handle_exception(); 162 } 163 164 static if (ARGS == 0) { 165 if (argCount == 0) { 166 return dg(); 167 } 168 } 111 169 T t; 112 170 foreach(i, arg; t) { 113 171 t[i] = d_type!(typeof(arg))(PyTuple_GetItem(args, i)); 114 172 } 115 116 static if (is(RT == void)) { 117 fn(t); 118 return; 173 return dg(t); 174 } 175 176 // wraps applyPyTupleToDelegate to return a PyObject* 177 PyObject* pyApplyToDelegate(dg_t) (dg_t dg, PyObject* args) { 178 static if (is(ReturnType!(dg_t) == void)) { 179 applyPyTupleToDelegate(dg, args); 180 Py_INCREF(Py_None); 181 return Py_None; 119 182 } else { 120 return fn(t);183 return _py( applyPyTupleToDelegate(dg, args) ); 121 184 } 122 185 } 123 186 124 187 template wrapped_func_call(fn_t) { 188 const uint ARGS = ParameterTypeTuple!(fn_t).length; 125 189 alias ReturnType!(fn_t) RT; 126 190 // The entry for the tp_call slot of the PydFunc types. … … 137 201 138 202 return exception_catcher({ 139 static if (is(RT == void)) { 140 py_call(fn, args); 141 Py_INCREF(Py_None); 142 return Py_None; 143 } else { 144 return _py( py_call(fn, args) ); 145 } 203 return pyApplyToDelegate(fn, args); 146 204 }); 147 205 } 148 206 } 149 207 150 // This is a handy shortcut that allows us to wrap a function alias directly 151 // with a PyCFunction. 152 template func_wrap(alias real_fn, uint MIN_ARGS, C=void, fn_t=typeof(&real_fn)) { 208 // Wraps a function alias with a PyCFunction. 209 template function_wrap(alias real_fn, uint MIN_ARGS, fn_t=typeof(&real_fn)) { 153 210 alias ParameterTypeTuple!(fn_t) Info; 154 211 const uint MAX_ARGS = Info.length; 155 212 alias ReturnType!(fn_t) RT; 156 213 157 // Wraps py_call to return a PyObject*158 PyObject* py_py_call(fn_t, PY)(fn_t fn, PY* args) {159 static if (is(RT == void)) {160 py_call(fn, args);161 Py_INCREF(Py_None);162 return Py_None;163 } else {164 return _py( py_call(fn, args) );165 }166 }167 168 // Calls py_py_call with the proper function contained in a tuple169 // returned from tuples.func_range.170 PyObject* tuple_py_call(PY, T ...)(PY* args, T t) {171 int argCount = 0;172 if (args !is null)173 argCount = PyObject_Length(args);174 175 static if (MIN_ARGS == 0) {176 if (argCount == 0)177 return py_py_call(&firstArgs!(real_fn, 0, fn_t), args);178 }179 foreach (i, arg; t) {180 if (ParameterTypeTuple!(typeof(arg)).length == argCount) {181 return py_py_call(arg, args);182 }183 }184 }185 186 214 extern (C) 187 215 PyObject* func(PyObject* self, PyObject* args) { 188 // For some reason, D can't infer the return type of this function189 // literal...190 216 return exception_catcher(delegate PyObject*() { 191 // If C is specified, then this is a method call. We need to pull out 192 // the object in self and turn the member function alias real_fn 193 // into a delegate. This conversion is done with a dirty hack; see 194 // dg_convert.d. 195 static if (!is(C == void)) { 196 static assert (MIN_ARGS == MAX_ARGS, "Default arguments with member functions are not supported."); 197 // Didn't pass a "self" parameter! Ack! 198 if (self is null) { 199 PyErr_SetString(PyExc_TypeError, "Wrapped method didn't get a 'self' parameter."); 200 return null; 201 } 202 C instance = (cast(wrapped_class_object!(C)*)self).d_obj; 203 fn_to_dg!(fn_t) fn = dg_wrapper!(C, fn_t)(instance, &real_fn); 204 static if (is(ReturnType!(typeof(fn)) == void)) { 205 py_call(fn, args); 206 Py_INCREF(Py_None); 207 return Py_None; 208 } else { 209 return _py( py_call(fn, args) ); 210 } 211 // If C is not specified, then this is just a normal function call. 212 } else { 213 alias defaultsTupleT!(real_fn, MIN_ARGS, fn_t).type T; 214 T t; 215 defaultsTuple!(real_fn, MIN_ARGS, fn_t)(delegate void(T tu) { 216 foreach(i, arg; tu) { 217 t[i] = arg; 218 } 219 }); 220 return tuple_py_call(args, t); 217 return pyApplyToAlias!(real_fn, fn_t, MIN_ARGS)(args); 218 }); 219 } 220 } 221 222 // Wraps a member function alias with a PyCFunction. 223 template method_wrap(C, alias real_fn, fn_t=typeof(&real_fn)) { 224 alias ParameterTypeTuple!(fn_t) Info; 225 const uint ARGS = Info.length; 226 alias ReturnType!(fn_t) RT; 227 extern(C) 228 PyObject* func(PyObject* self, PyObject* args) { 229 return exception_catcher(delegate PyObject*() { 230 // Didn't pass a "self" parameter! Ack! 231 if (self is null) { 232 PyErr_SetString(PyExc_TypeError, "Wrapped method didn't get a 'self' parameter."); 233 return null; 221 234 } 235 C instance = (cast(wrapped_class_object!(C)*)self).d_obj; 236 if (instance is null) { 237 PyErr_SetString(PyExc_ValueError, "Wrapped class instance is null!"); 238 return null; 239 } 240 fn_to_dg!(fn_t) dg = dg_wrapper!(C, fn_t)(instance, &real_fn); 241 return pyApplyToDelegate(dg, args); 222 242 }); 223 243 } trunk/infrastructure/pyd/make_object.d
r49 r50 144 144 } 145 145 // If it's not a wrapped type, fall through to the exception. 146 // This just passes the argument right back through without changing 147 // its reference count. 146 // The function expects to be passed a borrowed reference and return an 147 // owned reference. Thus, if passed a PyObject*, this will increment the 148 // reference count. 148 149 } else static if (is(T : PyObject*)) { 150 Py_INCREF(t); 149 151 return t; 150 152 } … … 178 180 * Calling this with a PydObject will return back a reference to the very same 179 181 * PydObject. 180 *181 * Calling this with a PyObject* will "steal" the reference.182 182 */ 183 183 PydObject py(T) (T t) { trunk/infrastructure/pyd/op_wrap.d
r47 r50 147 147 extern(C) 148 148 PyObject* func(PyObject* self) { 149 // func_wrap takes care of exception handling150 return func_wrap!(opfn, 0, T).func(self, null);149 // method_wrap takes care of exception handling 150 return method_wrap!(T, opfn, typeof(&opfn)).func(self, null); 151 151 } 152 152 } … … 205 205 return null; 206 206 } 207 return func_wrap!(T.opIndex, ARGS, T).func(self, key);207 return method_wrap!(T, T.opIndex, typeof(&T.opIndex)).func(self, key); 208 208 } 209 209 } … … 237 237 PyTuple_SetItem(temp, i, PyTuple_GetItem(key, i-1)); 238 238 } 239 func_wrap!(T.opIndexAssign, ARGS, T).func(self, temp);239 method_wrap!(T, T.opIndexAssign, typeof(&T.opIndexAssign)).func(self, temp); 240 240 return 0; 241 241 }
