Changeset 57
- Timestamp:
- 12/12/06 23:49:57 (5 years ago)
- Files:
-
- trunk/examples/inherit/inherit.d (modified) (2 diffs)
- trunk/examples/inherit/test.py (modified) (1 diff)
- trunk/examples/testdll/testdll.d (modified) (2 diffs)
- trunk/html_doc/basics.html (modified) (1 diff)
- trunk/html_doc/celerid.html (modified) (1 diff)
- trunk/html_doc/class_wrapping.html (modified) (2 diffs)
- trunk/html_doc/conversion.html (modified) (1 diff)
- trunk/html_doc/credits.html (modified) (1 diff)
- trunk/html_doc/except_wrapping.html (modified) (1 diff)
- trunk/html_doc/func_wrapping.html (modified) (1 diff)
- trunk/html_doc/index.html (modified) (1 diff)
- trunk/html_doc/install.html (modified) (1 diff)
- trunk/html_doc/pydobject.html (modified) (1 diff)
- trunk/html_doc/struct_wrapping.html (modified) (1 diff)
- trunk/html_doc/vsboost.html (added)
- trunk/infrastructure/pyd/class_wrap.d (modified) (1 diff)
- trunk/infrastructure/pyd/exception.d (modified) (2 diffs)
- trunk/infrastructure/pyd/func_wrap.d (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/examples/inherit/inherit.d
r56 r57 19 19 } 20 20 21 class WrapDerive : Derived { 22 mixin OverloadShim; 23 void foo() { 24 get_overload(&super.foo, "foo"); 25 } 26 } 27 21 28 void call_poly(Base b) { 22 writef ("call_poly:");29 writefln("call_poly:"); 23 30 b.foo(); 24 31 } … … 38 45 d.def!(Derived.foo); 39 46 finalize_class(d); 47 48 wrapped_class!(WrapDerive) w; 49 w.def!(WrapDerive.foo); 50 finalize_class(w); 40 51 } trunk/examples/inherit/test.py
r56 r57 26 26 inherit.call_poly(d) 27 27 28 class PyClass(inherit.Derived): 28 w = inherit.WrapDerive() 29 inherit.call_poly(w) 30 31 class PyClass(inherit.WrapDerive): 29 32 def foo(self): 30 33 print 'PyClass.foo' 31 34 32 35 p = PyClass() 33 print "The basic inheritance support breaks down here:"36 #print "The basic inheritance support breaks down here:" 34 37 inherit.call_poly(p) trunk/examples/testdll/testdll.d
r52 r57 124 124 } 125 125 126 void throws() { 127 throw new Exception("Yay! An exception!"); 128 } 129 126 130 extern (C) 127 131 export void inittestdll() { … … 139 143 def!(func_test); 140 144 def!(dg_test); 145 def!(throws); 141 146 142 147 module_init("testdll"); trunk/html_doc/basics.html
r52 r57 20 20 <a class="nav" href="except_wrapping.html">Exception wrapping</a><br /> 21 21 <a class="nav" href="pydobject.html">PydObject</a><br /> 22 <a class="nav" href="vsboost.html">vs. Boost.Python</a><br /> 22 23 <a class="nav" href="credits.html">Credits</a> 23 24 </div> trunk/html_doc/celerid.html
r52 r57 20 20 <a class="nav" href="except_wrapping.html">Exception wrapping</a><br /> 21 21 <a class="nav" href="pydobject.html">PydObject</a><br /> 22 <a class="nav" href="vsboost.html">vs. Boost.Python</a><br /> 22 23 <a class="nav" href="credits.html">Credits</a> 23 24 </div> trunk/html_doc/class_wrapping.html
r52 r57 20 20 <a class="nav" href="except_wrapping.html">Exception wrapping</a><br /> 21 21 <a class="nav" href="pydobject.html">PydObject</a><br /> 22 <a class="nav" href="vsboost.html">vs. Boost.Python</a><br /> 22 23 <a class="nav" href="credits.html">Credits</a> 23 24 </div> … … 103 104 <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> 104 105 </dl> 106 107 <h3><a class="anchor" name="inheritance">Inheritance</a></h3> 108 109 <p>If you wrap both a class and a child of that class, Pyd is smart enough to make the resulting Python classes have a parent-child relationship. Any methods of the parent class will automatically be available to the child class. If the child class overloads any of those methods, it is important that the user wrap them in the module's init function. For example:</p> 110 111 <pre class="code"><span class="keyword">import</span> std.stdio; 112 113 <span class="keyword">class</span> Base { 114 <span class="keyword">void</span> foo() { writefln(<span class="string">"Base.foo"</span>); } 115 <span class="keyword">void</span> bar() { writefln(<span class="string">"Base.bar"</span>); } 116 } 117 118 <span class="keyword">class</span> Derived : Base { 119 <span class="keyword">void</span> foo() { writefln(<span class="string">"Derived.foo"</span>); } 120 }</pre> 121 122 <p>These would be exposed to Python by putting this code in out init function after the call to <code>module_init</code>:</p> 123 124 <pre class="code">wrapped_class!(Base) b; 125 b.def!(Base.foo); 126 b.def!(Base.bar); 127 finalize_class(b); 128 129 wrapped_class!(Derived) d; 130 d.def!(Derived.foo); 131 finalize_class(d);</pre> 132 133 <p>When used in Python, we get the expected behavior:</p> 134 135 <pre class="code">>>> issubclass(Derived, Base) 136 True 137 >>> b = Base() 138 >>> d = Derived() 139 >>> b.foo() 140 Base.foo 141 >>> b.bar() 142 Base.bar 143 >>> d.foo() 144 Derived.foo 145 >>> d.bar() 146 Base.bar</pre> 147 148 <p>There is one weakness in the default behavior. Take a function like the following:</p> 149 150 <pre class="code"><span class="keyword">void</span> polymorphic_call(Base b) { 151 b.foo(); 152 }</pre> 153 154 <p>And in Python:</p> 155 156 <pre class="code"><span class="keyword">class</span> PyClass(Base): 157 <span class="keyword">def</span> foo(self): 158 <span class="keyword">print</span> <span class="string">"PyClass.foo"</span> 159 160 >>> p = PyClass() 161 >>> polymorphic_call(p) 162 Base.foo</pre> 163 164 <p>Optimally, we would want <code>polymorphic_call</code> to call PyClass.foo. This requires some additional work on the D side of things. To get this behavior, then rather than expose Base directly, we must expose a wrapper class:</p> 165 166 <pre class="code"><span class="keyword">class</span> BaseWrap : Base { 167 <span class="keyword">mixin</span> OverloadShim; 168 <span class="keyword">void</span> foo() { 169 get_overload(&<span class="keyword">super</span>.foo, <span class="string">"foo"</span>); 170 } 171 <span class="keyword">void</span> bar() { 172 get_overload(&<span class="keyword">super</span>.bar, <span class="string">"bar"</span>); 173 } 174 }</pre> 175 176 <p>Now, we must replace the old wrapping of Base with this:</p> 177 178 <pre class="code">wrapped_class!(BaseWrap, <span class="string">"Base"</span>) w; 179 w.def!(BaseWrap.foo); 180 w.def!(BaseWrap.bar); 181 finalize_class(w);</pre> 182 183 <p>Now our subclass will perform just like we expect:</p> 184 185 <pre class="code">>>> p = PyClass() 186 >>> polymorphic_call(p) 187 PyClass.foo</pre> 105 188 106 189 <h3><a class="anchor" name="examples">Examples</a></h3> trunk/html_doc/conversion.html
r52 r57 20 20 <a class="nav" href="except_wrapping.html">Exception wrapping</a><br /> 21 21 <a class="nav" href="pydobject.html">PydObject</a><br /> 22 <a class="nav" href="vsboost.html">vs. Boost.Python</a><br /> 22 23 <a class="nav" href="credits.html">Credits</a> 23 24 </div> trunk/html_doc/credits.html
r52 r57 20 20 <a class="nav" href="except_wrapping.html">Exception wrapping</a><br /> 21 21 <a class="nav" href="pydobject.html">PydObject</a><br /> 22 <a class="nav" href="vsboost.html">vs. Boost.Python</a><br /> 22 23 <a class="navcur" href="credits.html">Credits</a> 23 24 </div> trunk/html_doc/except_wrapping.html
r52 r57 20 20 <a class="navcur" href="except_wrapping.html">Exception wrapping</a><br /> 21 21 <a class="nav" href="pydobject.html">PydObject</a><br /> 22 <a class="nav" href="vsboost.html">vs. Boost.Python</a><br /> 22 23 <a class="nav" href="credits.html">Credits</a> 23 24 </div> trunk/html_doc/func_wrapping.html
r52 r57 20 20 <a class="nav" href="except_wrapping.html">Exception wrapping</a><br /> 21 21 <a class="nav" href="pydobject.html">PydObject</a><br /> 22 <a class="nav" href="vsboost.html">vs. Boost.Python</a><br /> 22 23 <a class="nav" href="credits.html">Credits</a> 23 24 </div> trunk/html_doc/index.html
r52 r57 20 20 <a class="nav" href="except_wrapping.html">Exception wrapping</a><br /> 21 21 <a class="nav" href="pydobject.html">PydObject</a><br /> 22 <a class="nav" href="vsboost.html">vs. Boost.Python</a><br /> 22 23 <a class="nav" href="credits.html">Credits</a> 23 24 </div> trunk/html_doc/install.html
r52 r57 20 20 <a class="nav" href="except_wrapping.html">Exception wrapping</a><br /> 21 21 <a class="nav" href="pydobject.html">PydObject</a><br /> 22 <a class="nav" href="vsboost.html">vs. Boost.Python</a><br /> 22 23 <a class="nav" href="credits.html">Credits</a> 23 24 </div> trunk/html_doc/pydobject.html
r52 r57 20 20 <a class="nav" href="except_wrapping.html">Exception wrapping</a><br /> 21 21 <a class="navcur" href="pydobject.html">PydObject</a><br /> 22 <a class="nav" href="vsboost.html">vs. Boost.Python</a><br /> 22 23 <a class="nav" href="credits.html">Credits</a> 23 24 </div> trunk/html_doc/struct_wrapping.html
r52 r57 20 20 <a class="nav" href="except_wrapping.html">Exception wrapping</a><br /> 21 21 <a class="nav" href="pydobject.html">PydObject</a><br /> 22 <a class="nav" href="vsboost.html">vs. Boost.Python</a><br /> 22 23 <a class="nav" href="credits.html">Credits</a> 23 24 </div> trunk/infrastructure/pyd/class_wrap.d
r56 r57 447 447 } 448 448 449 import std.stdio; 450 451 template OverloadShim() { 452 std.traits.ReturnType!(dg_t) get_overload(dg_t, T ...) (dg_t dg, char[] name, T t) { 453 python.PyObject* _pyobj = wrapped_gc_objects[cast(void*)this]; 454 if (_pyobj.ob_type != &wrapped_class_type!(typeof(this))) { 455 //writefln("Wrapper class, calling wrapped PyObject"); 456 // If this object's type is not the wrapped class's type (that is, 457 // if this object is actually a Python subclass of the wrapped 458 // class), then call the Python object. 459 python.PyObject* method = python.PyObject_GetAttrString(_pyobj, (name ~ \0).ptr); 460 if (method is null) handle_exception(); 461 dg_t pydg = PydCallable_AsDelegate!(dg_t)(method); 462 python.Py_DECREF(method); 463 return pydg(t); 464 } else { 465 //writefln("Wrapper class, calling original delegate"); 466 return dg(t); 467 } 468 } 469 } 470 449 471 /////////////////////// 450 472 // PYD API FUNCTIONS // trunk/infrastructure/pyd/exception.d
r55 r57 25 25 private import meta.Nameof; 26 26 private import std.string; 27 import std.stdio; 27 28 28 29 /** … … 106 107 107 108 ~this() { 108 Py_DECREF(m_type);109 Py_DECREF(m_value);110 Py_DECREF(m_trace);109 if (m_type) Py_DECREF(m_type); 110 if (m_value) Py_DECREF(m_value); 111 if (m_trace) Py_DECREF(m_trace); 111 112 } 112 113 113 114 PyObject* type() { 114 Py_INCREF(m_type);115 if (m_type) Py_INCREF(m_type); 115 116 return m_type; 116 117 } 117 118 PyObject* value() { 118 Py_INCREF(m_value);119 if (m_value) Py_INCREF(m_value); 119 120 return m_value; 120 121 } 121 122 PyObject* traceback() { 122 Py_INCREF(m_trace);123 if (m_trace) Py_INCREF(m_trace); 123 124 return m_trace; 124 125 } trunk/infrastructure/pyd/func_wrap.d
r54 r57 88 88 } 89 89 90 import std.stdio; 91 90 92 // Calls callable alias fn with PyTuple args. 91 93 ReturnType!(fn_t) applyPyTupleToAlias(alias fn, fn_t, uint MIN_ARGS) (PyObject* args) { … … 99 101 argCount = PyObject_Length(args); 100 102 } 103 //writefln("argCount: %s; MIN_ARGS: %s; MAX_ARGS: %s", argCount, MIN_ARGS, MAX_ARGS); 101 104 102 105 // Sanity check! … … 196 199 fn_t fn = (cast(wrapped_class_object!(fn_t)*)self).d_obj; 197 200 198 return exception_catcher( {201 return exception_catcher(delegate PyObject*() { 199 202 return pyApplyToDelegate(fn, args); 200 203 });
