Changeset 102

Show
Ignore:
Timestamp:
02/22/07 18:29:52 (2 years ago)
Author:
KirkMcDonald
Message:

Updated docs with new class-wrapping API.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/html_doc/basics.html

    r86 r102  
    5151<p>It does little more than call <a href="http://docs.python.org/api/allocating-objects.html">Py_InitModule</a> and return the new module object. This object is also available via the <code>Pyd_Module_p</code> property once you've called <code>module_init</code>.</p> 
    5252 
    53 <p>Due to the way in which Pyd implements function and class wrapping, any calls to <code>def</code> must occur <em>before</em> the call to <code>module_init</code>, and any calls to <code>finalize_class</code> must occur <em>after</em> the call. I know this seems like a rather arbitrary rule, but it is important. Calls to <code>def</code> in the wrong place will simply be ignored, and calls to <code>finalize_class</code> in the wrong place will throw an assert.</p> 
     53<p>Due to the way in which Pyd implements function and class wrapping, any calls to <code>def</code> must occur <em>before</em> the call to <code>module_init</code>, and any calls to <code>wrap_class</code> must occur <em>after</em> the call. I know this seems like a rather arbitrary rule, but it is important. Calls to <code>def</code> in the wrong place will simply be ignored, and calls to <code>wrap_class</code> in the wrong place will throw an assert.</p> 
    5454 
    5555<p><code>PydMain</code> will catch any D exception that is thrown from inside it, and <a href="except_wrapping.html">safely pass that exception to Python</a>.</p> 
  • trunk/html_doc/celerid.html

    r86 r102  
    5858    <dt><code>raw_only</code></dt> <dd>This flag defaults to <code>False</code>. When <code>True</code>, it supresses the compilation and linkage of Pyd, StackThreads, and meta. This is useful if you only want to write a raw Python/C extension without the overhead of Pyd and its auxiliary packages. This is equivalent to specifying <code>False</code> to the next four flags.</dd> 
    5959    <dt><code>with_pyd</code></dt> <dd>This flag defaults to <code>True</code>. When <code>False</code>, it supresses the compilation and linkage of Pyd. This is useful if you want to write a raw Python/C extension and don't want the overhead of compiling Pyd.</dd> 
    60     <dt><code>with_st</code></dt> <dd>This flag defaults to <code>True</code>. When <code>False</code>, it supresses the compilation and linkage of StackThreads. Pyd uses StackThreads for its iteration wrapping support. By setting this to <code>False</code>, opApply wrapping, <code>wrapped_class.iter</code>, and <code>wrapped_class.alt_iter</code> will be unavailable. If <code>with_pyd</code> and this are <code>True</code>, then the <code>Pyd_with_StackThreads</code> version flag will be defined (which is used internally by Pyd). <b>Important note:</b> StackThreads does not currently work with GDC! CeleriD will always set this flag to <code>False</code> when using GDC! This means that opApply wrapping is not available on Linux at this time.</dd> 
     60    <dt><code>with_st</code></dt> <dd>This flag defaults to <code>True</code>. When <code>False</code>, it supresses the compilation and linkage of StackThreads. Pyd uses StackThreads for its iteration wrapping support. By setting this to <code>False</code>, opApply wrapping, <code>Iter</code>, and <code>AltIter</code> will be unavailable. If <code>with_pyd</code> and this are <code>True</code>, then the <code>Pyd_with_StackThreads</code> version flag will be defined (which is used internally by Pyd). <b>Important note:</b> StackThreads does not currently work with GDC! CeleriD will always set this flag to <code>False</code> when using GDC! This means that opApply wrapping is not available on Linux at this time.</dd> 
    6161    <dt><code>with_meta</code></dt> <dd>This flag defaults to <code>True</code>. When <code>False</code>, it supresses the compilation and linkage of <code>meta</code> (Pyd's metaprogramming package). Because Pyd depends on meta, an exception will be raised if <code>with_pyd</code> is <code>True</code> and this is not.</dd> 
    6262    <dt><code>with_main</code></dt> <dd>This flag defaults to <code>True</code>. When <code>False</code>, it supresses the use of the "magic" <code>PydMain</code> function. (Instead, users must manually declare a C-style <code>init</code> function.) Do not use this unless you know what you are doing. If <code>with_pyd</code> is <code>False</code>, this will silently be set to <code>False</code> as well. <code>PydMain</code> can only be used if Pyd itself is in use.</dd> 
  • trunk/html_doc/class_wrapping.html

    r91 r102  
    2929<h1>Class wrapping</h1> 
    3030 
    31 <p>Exposing D classes to Python is easy! The heart of Pyd's class wrapping features is the <code>wrapped_class</code> template struct:</p> 
     31<p>Exposing D classes to Python is easy! The heart of Pyd's class wrapping features is the <code>wrap_class</code> function template:</p> 
    3232 
    33 <p><code>struct wrapped_class(<span class="t_arg">T</span>, char[] <span class="t_arg">classname</span> = symbolnameof!(T));</code></p> 
     33<p><code>void wrap_class(<span class="t_arg">T</span>, char[] <span class="t_arg">classname</span> = symbolnameof!(T), <span class="t_arg">Params</span>...) ();</code></p> 
    3434    <ul> 
    3535    <li><span class="t_arg">T</span> is the class being wrapped.</li> 
    36     <li><span class="t_arg">classname</span> is the name of the class as it will appear in Python.</li> 
     36    <li><span class="t_arg">classname</span> is the name of the class as it will appear in Python. It defaults to the name of the D class. If you are wrapping an instance of a class template, you will have to provide this explicitly.</li> 
     37    <li><span class="t_arg">Params</span> is a series of struct types (defined below), which define the various members of the class.</li> 
    3738    </ul> 
    3839 
    39 <p>To expose the constructors, methods, and properties of the class, <code>wrapped_class</code> provides a series of template member functions.</p> 
     40<p>Calls to <code>wrap_class</code> must occur <em>after</em> calling <code>module_init</code>.</p> 
     41 
     42<p>To expose the constructors, methods, and properties of the class, you must pass <code>wrap_class</code> instantiations of these struct templates.</p> 
    4043 
    4144<dl> 
    42 <dt><code>static void def(alias <span class="t_arg">fn</span>, char[] <span class="t_arg">name</span> = symbolnameof!(fn), <span class="t_arg">fn_t</span> = typeof(&amp;fn)) (char[] <span class="arg">docstring</span>="");</code></dt> 
    43 <dd>This wraps a method of the class. It functions exactly like the <code>def</code> function used to <a href="func_wrapping.html">wrap regular functions</a>, with one very important difference: There is no support for default arguments. (This is a side-effect of the fact that you cannot call an alias of a method in D, and delegates do not understand default arguments.)</dd> 
     45<dt><code>struct Def(alias <span class="t_arg">fn</span>, char[] <span class="t_arg">name</span> = symbolnameof!(fn), <span class="t_arg">fn_t</span> = typeof(&amp;fn));</code></dt> 
     46<dd>This wraps a method of the class. It functions very much like the <code>def</code> function used to <a href="func_wrapping.html">wrap regular functions</a>, with one very important difference: There is no support for default arguments. (This is a side-effect of the fact that you cannot call an alias of a method in D, and delegates do not understand default arguments.)</dd> 
    4447 
    45 <dt><code>static void static_def(alias <span class="t_arg">fn</span>, char[] <span class="t_arg">name</span> = symbolnameof!(fn), <span class="t_arg">fn_t</span> = typeof(&amp;fn), uint <span class="t_arg">MIN_ARGS</span> = minArgs!(fn)) (char[] <span class="arg">docstring</span>="");</code></dt> 
     48<dt><code>struct StaticDef(alias <span class="t_arg">fn</span>, char[] <span class="t_arg">name</span> = symbolnameof!(fn), <span class="t_arg">fn_t</span> = typeof(&amp;fn), uint <span class="t_arg">MIN_ARGS</span> = minArgs!(fn));</code></dt> 
    4649<dd>This wraps a static member function of the class. It also functions exactly like the <code>def</code> function used to wrap regular functions, and even includes support for default arguments.</dd> 
    4750 
    48 <dt><code>static void prop(alias <span class="t_arg">fn</span>, char[] <span class="t_arg">name</span> = symbolnameof!(fn), bool <span class="t_arg">RO</span> = false) (char[] <span class="arg">docstring</span>="");</code></dt> 
     51<dt><code>struct Property(alias <span class="t_arg">fn</span>, char[] <span class="t_arg">name</span> = symbolnameof!(fn), bool <span class="t_arg">RO</span> = false);</code></dt> 
    4952<dd>This wraps a property. See the examples below for more details. 
    5053    <ul> 
     
    5255    <li><span class="t_arg">name</span> is the name of the property as it will appear in Python. As with <code>def</code>, <code>prop</code> will attempt to derive this automatically.</li> 
    5356    <li><span class="t_arg">RO</span> specifies whether this is a <i>read-only</i> property. If true, it will only wrap the "get" form of the property. If false, it will wrap both the "get" and "set" forms. <i>(This is a little hackish, and I will probably try to make this detection more automatic in the future. It also means it cannot support a property that only has a "set" form.)</i></li> 
    54     <li><span class="arg">docstring</span> is the property's docstring. As usual, note that this is a regular function argument, and not a template argument.</li> 
    5557    </ul> 
    5658</dd> 
    5759 
    58 <dt><code>static void init(<span class="t_arg">C</span> ...) ();</code></dt> 
    59 <dd>This allows you to expose the class's constructors to Python. If the class provides a zero-argument constructor, there is no need to specify it; it is always available. Each element of <span class="t_arg">C</span> should be a function type. Each function type should correspond to a constructor. (That is, the arguments to the function should be the same as arguments to the class constructor. The return type is ignored.) There is an additional limitation at this time: No two constructors may have the same number of arguments. Pyd will always attempt to call the first constructor with the right number of arguments. If you wish to support a constructor with default arguments, you must specify each possible constructor call as a different template argument to this function. The examples show a few uses of the <code>init</code> function.</dd> 
     60<dt><code>struct Init(<span class="t_arg">C</span> ...);</code></dt> 
     61<dd>This allows you to expose the class's constructors to Python. If the class provides a zero-argument constructor, there is no need to specify it; it is always available. Each element of <span class="t_arg">C</span> should be a function type. Each function type should correspond to a constructor. (That is, the arguments to the function type should be the same as the arguments to the class constructor. The return type is ignored.) There is an additional limitation at this time: No two constructors may have the same number of arguments. Pyd will always attempt to call the first constructor with the right number of arguments. If you wish to support a constructor with default arguments, you must specify each possible constructor call as a different template argument to this function. The examples show a few uses of the <code>init</code> function.</dd> 
    6062 
    61 <dt><code>static void parent(<span class="t_arg">Parent</span>) ();</code></dt> 
    62 <dd>This allows the user to manually specify a class as this class's parent. This is intended for a very specific purpose (related to how Pyd handles <a href="inherit.html">inheritance</a>), and should not be used heedlessly. If a class's parent was previously wrapped, then Pyd will detect this and set up a parent-child relationship automatically, in which case it is not neccessary to specify this.</dd> 
    63  
    64 <dt><code>static void hide();</code></dt> 
    65 <dd>Causes this class to be wrapped, but not actually directly exposed to Python. This can be useful if you want to return instances of a class without allowing Python code to instantiate them. This is mainly used when handling <a href="inherit.html">inheritance</a>.</dd> 
    66  
    67 <dt><code>static void iter(<span class="t_arg">iter_t</span>) ();</code></dt> 
     63<dt><code>struct Iter(<span class="t_arg">iter_t</span>);</code></dt> 
    6864<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! (This is not available in Linux; see the note below on opApply wrapping.)</dd> 
    6965 
    70 <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>) (char[] <span class="arg">docstring</span>="");</code></dt> 
     66<dt><code>struct AltIter(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> 
    7167<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. (This is not available in Linux; see the note below on opApply wrapping.) 
    7268</dd> 
    7369</dl> 
    74  
    75 <p>Once you have called all of the member functions of <code>wrapped_class</code> that you wish to, you must issue a call to <code>finalize_class</code>.</p> 
    76  
    77 <p><code>void finalize_class(<span class="t_arg">CLS</span>) (<span class="t_arg">CLS</span> <span class="arg">cls</span>, char[] <span class="arg">docstring</span>="");</code></p> 
    78  
    79 <p>This does some final initialization of the class and then registers it with Python. Unlike calls to <a href="func_wrapping.html"><code>def</code></a>, calls to <code>finalize_class</code> must occur <em>after</em> calling <code>module_init</code>. The <span class="arg">cls</span> function argument should be an instance of <code>wrapped_class</code>.</p> 
    8070 
    8171<p>If you ever wish to check whether a given class has been wrapped, Pyd helpfully registers all wrapped classes with the <code>is_wrapped</code> template, which is just a templated <code>bool</code>:</p> 
     
    9686<p>At the moment, only the following operator overloads are supported:</p> 
    9787 
    98 <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> 
     88<p><code>opNeg, opPos, opCom, 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> 
    9989 
    100 <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> 
     90<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>Def</code>, of course.) Also missing from the list is <code>opApplyReverse</code>. This must be wrapped explicitly with <code>AltIter</code>.</p> 
    10191 
    10292<p>Also missing from the list is <code>opAssign</code>. Python has strict reference semantics for its objects, so overloading the assignment operator is not possible. You must explicitly wrap <code>opAssign</code> with a regular method.</p> 
    10393 
    104 <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> and the special <code>__len__</code> method. 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> 
     94<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> and the special <code>__len__</code> method. You may still wrap it with <code>Property</code> or <code>Def</code> if you wish it to be available as a normal property or method.</p> 
    10595 
    10696<p><b>Notes on wrapped operators</b></p> 
     
    140130<p>We would expose this class to Python by putting this code in <code>PydMain</code> after the call to <code>module_init</code>:</p> 
    141131 
    142 <pre class="code"><span class="comment">// Make an instance of wrapped_class</span> 
    143 wrapped_class!(Foo) f; 
    144 <span class="comment">// Wrap the "foo" method</span> 
    145 f.def!(Foo.foo); 
    146 <span class="comment">// Wrap the "i" property</span> 
    147 f.prop!(Foo.i); 
    148 <span class="comment">// Wrap the constructors.</span> 
    149 f.init!(<span class="keyword">void function</span>(<span class="keyword">int</span>), <span class="keyword">void function</span>(<span class="keyword">int</span>, <span class="keyword">int</span>)); 
    150 finalize_class(f);</pre> 
     132<pre class="code"><span class="comment">// Call wrap_class</span> 
     133wrap_class!( 
     134    Foo, 
     135    <span class="comment">// Wrap the "foo" method</span> 
     136    Def!(Foo.foo), 
     137    <span class="comment">// Wrap the "i" property</span> 
     138    Property!(Foo.i), 
     139    <span class="comment">// Wrap the constructors.</span> 
     140    Init!(<span class="keyword">void function</span>(<span class="keyword">int</span>), <span class="keyword">void function</span>(<span class="keyword">int</span>, <span class="keyword">int</span>)) 
     141);</pre> 
    151142 
    152143<p>Now we can use this type from within Python like any other type.</p> 
    153144 
    154 <pre class="code">&gt;&gt;&gt; from testmodule import Foo 
     145<pre class="code">&gt;&gt;&gt; <span class="keyword">from</span> testmodule <span class="keyword">import</span> Foo 
    155146&gt;&gt;&gt; f = Foo() 
    156147&gt;&gt;&gt; f.i 
    1571480 
    158149&gt;&gt;&gt; f.i = 20 
    159 &gt;&gt;&gt; f.foo("Hello! i is "
     150&gt;&gt;&gt; f.foo(<span class="string">"Hello! i is "</span>
    160151Hello! i is 20 
    161152&gt;&gt;&gt; f = Foo(10, 10) 
     
    168159&gt;&gt;&gt; e.i 
    16916050 
    170 &gt;&gt;&gt; # We can even subclass our D type 
    171 &gt;&gt;&gt; class MyFoo(Foo): 
    172 ...     def bar(self): 
    173 ...         print "Hey, i+3 is", self.i + 3 
     161&gt;&gt;&gt; <span class="comment"># We can even subclass our D type</span> 
     162&gt;&gt;&gt; <span class="keyword">class</span> MyFoo(Foo): 
     163...     <span class="keyword">def</span> bar(self): 
     164...         <span class="keyword">print</span> <span class="string">"Hey, i+3 is"</span>, self.i + 3 
    174165...  
    175166&gt;&gt;&gt; h = MyFoo(3) 
  • trunk/html_doc/inherit.html

    r91 r102  
    4444<p>These would be exposed to Python by putting this code in <code>PydMain</code> after the call to <code>module_init</code>:</p> 
    4545 
    46 <pre class="code">wrapped_class!(Base) b; 
    47 b.def!(Base.foo); 
    48 b.def!(Base.bar); 
    49 finalize_class(b); 
     46<pre class="code">wrap_class!( 
     47    Base, 
     48    Def!(Base.foo), 
     49    Def!(Base.bar), 
     50); 
    5051 
    51 wrapped_class!(Derived) d; 
    52 d.def!(Derived.foo); 
    53 finalize_class(d);</pre> 
     52wrap_class!( 
     53    Derived, 
     54    Def!(Derived.foo), 
     55);</pre> 
    5456 
    5557<p>When used in Python, we get the expected behavior:</p> 
     
    6870Base.bar</pre> 
    6971 
    70 <p>There is one weakness in the default behavior. Take a function like the following:</p> 
     72<p>Polymorphic behavior is also automatically taken care of. Take a function like the following:</p> 
    7173 
    7274<pre class="code"><span class="keyword">void</span> polymorphic_call(Base b) { 
     
    7678<p>And in Python:</p> 
    7779 
    78 <pre class="code"><span class="keyword">class</span> PyClass(Base): 
    79     <span class="keyword">def</span> foo(self): 
    80         <span class="keyword">print</span> <span class="string">"PyClass.foo"</span> 
    81  
     80<pre class="code">&gt;&gt;&gt; <span class="keyword">class</span> PyClass(Base): 
     81...    <span class="keyword">def</span> foo(self): 
     82...        <span class="keyword">print</span> <span class="string">"PyClass.foo"</span> 
     83...  
    8284&gt;&gt;&gt; p = PyClass() 
    8385&gt;&gt;&gt; polymorphic_call(p) 
    84 Base.foo</pre> 
    85  
    86 <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> 
    87  
    88 <pre class="code"><span class="keyword">class</span> BaseWrap : Base { 
    89     <span class="keyword">mixin</span> OverloadShim; 
    90     <span class="keyword">void</span> foo() { 
    91         get_overload(&amp;<span class="keyword">super</span>.foo, <span class="string">"foo"</span>); 
    92     } 
    93     <span class="keyword">void</span> bar() { 
    94         get_overload(&amp;<span class="keyword">super</span>.bar, <span class="string">"bar"</span>); 
    95     } 
    96 }</pre> 
    97  
    98 <p>The <code>OverloadShim</code> template has but a single member, the <code>get_overload</code> function.</p> 
    99  
    100 <dl> 
    101 <dt><code>ReturnType!(dg_t) get_overload(<span class="t_arg">dg_t</span>, <span class="t_arg">T ...</span>) (dg_t <span class="arg">dg</span>, char[] <span class="arg">name</span>, T <span class="arg">t</span>);</code></dt> 
    102 <dd><ul> 
    103     <li><span class="arg">dg</span> should be a delegate to the parent class's method.</li> 
    104     <li><span class="arg">name</span> should be the name of the method as Python understands it to be. <i>(There's no efficient way to derive this automatically based on only the delegate.)</i></li> 
    105     <li><span class="arg">t</span> is a tuple argument. These arguments will be passed on to the actual function call, be it the parent class's implementation or a Python subclass's implementation.</li> 
    106 </ul></dd> 
    107 </dl> 
    108  
    109 <p><code>get_overload</code> returns whatever the method does.</p> 
    110  
    111 <p>Now, we must replace the old wrapping of Base with this:</p> 
    112  
    113 <pre class="code">wrapped_class!(BaseWrap, <span class="string">"Base"</span>) w; 
    114 w.def!(BaseWrap.foo); 
    115 w.def!(BaseWrap.bar); 
    116 finalize_class(w);</pre> 
    117  
    118 <p>Now our subclass will perform just like we expect:</p> 
    119  
    120 <pre class="code">&gt;&gt;&gt; p = PyClass() 
    121 &gt;&gt;&gt; polymorphic_call(p) 
    12286PyClass.foo</pre> 
    123  
    124 <p>However, BaseWrap has no particular relationship to Derived. You may remember that Derived overloads <tt>bar</tt> but not <tt>foo</tt>. When we wrapped Derived in <tt>PydMain</tt>, we specified the <tt>foo</tt> overload but not the <tt>bar</tt> overload. Because Derived's parent class is no longer wrapped, Pyd no longer has any way to know about the <tt>bar</tt> method of the Derived class.</tt></p> 
    125  
    126 <p>The solution is to explicitly tell Pyd that Derived's parent is BaseWrap. Furthermore, it is probably best to go the extra mile, by wrapping an <tt>OverloadShim</tt> subclass of Derived (call it DerivedWrap), and telling Pyd that BaseWrap is <em>its</em> parent. Additionally, the original <tt>Base</tt> and <tt>Derived</tt> classes should still be wrapped, in the event that functions return instances of them to Python, but should not actually be exposed to Python. The complete solution ends up looking like this:</p> 
    127  
    128 <pre class="code"><span class="keyword">import</span> pyd.pyd; 
    129 <span class="keyword">import</span> std.stdio; 
    130  
    131 <span class="keyword">class</span> Base { 
    132     <span class="keyword">void</span> foo() { writefln(<span class="string">"Base.foo"</span>); } 
    133     <span class="keyword">void</span> bar() { writefln(<span class="string">"Base.bar"</span>); } 
    134 } 
    135  
    136 <span class="keyword">class</span> Derived : Base { 
    137     <span class="keyword">void</span> foo() { writefln(<span class="string">"Derived.foo"</span>); } 
    138 } 
    139  
    140 <span class="keyword">class</span> BaseWrap : Base { 
    141     <span class="keyword">mixin</span> OverloadShim; 
    142     <span class="keyword">void</span> foo() { 
    143         get_overload(&amp;<span class="keyword">super</span>.foo, <span class="string">"foo"</span>); 
    144     } 
    145     <span class="keyword">void</span> bar() { 
    146         get_overload(&amp;<span class="keyword">super</span>.bar, <span class="string">"bar"</span>); 
    147     } 
    148 } 
    149  
    150 <span class="keyword">class</span> DerivedWrap : Derived { 
    151     <span class="keyword">mixin</span> OverloadShim; 
    152     <span class="keyword">void</span> foo() { 
    153         get_overload(&amp;<span class="keyword">super</span>.foo, <span class="string">"foo"</span>); 
    154     } 
    155 } 
    156  
    157 <span class="keyword">extern</span> (C) <span class="keyword">void</span> PydMain() { 
    158     module_init(); 
    159  
    160     wrapped_class!(Base) b; 
    161     w.hide(); 
    162     w.def!(Base.foo); 
    163     w.def!(Base.bar); 
    164     finalize_class(w); 
    165  
    166     wrapped_class!(Derived) d; 
    167     d.hide(); 
    168     d.def!(Derived.foo); 
    169     finalize_class(d); 
    170  
    171     wrapped_class!(BaseWrap, <span class="string">"Base"</span>) bw; 
    172     bw.def!(BaseWrap.foo); 
    173     bw.def!(BaseWrap.bar); 
    174     finalize_class(bw); 
    175  
    176     wrapped_class!(DerivedWrap, <span class="string">"Derived"</span>) dw; 
    177     dw.parent!(BaseWrap); 
    178     dw.def!(DerivedWrap.foo); 
    179     finalize_class(dw); 
    180 }</pre> 
    181  
    182 <p><i>(I recognize that this is astoundingly ugly. However, it is the best solution I can come up with without resorting to code generation.)</i></p> 
    183  
    184 <p>The <a href="http://dsource.org/projects/pyd/browser/trunk/examples/inherit/inherit.d"><tt>inherit</tt> example</a> in the Pyd distribution provides a more complete version of this example, including how wrapper code should handle constructors.</p> 
    18587 
    18688<p><i>(TODO: Add support for interfaces and abstract classes.)</i></p> 
  • trunk/html_doc/struct_wrapping.html

    r86 r102  
    3131<p>Wrapping D's structs is similar to wrapping classes. In fact, many of the operations are identical.</p> 
    3232 
    33 <p><code>struct wrapped_struct(<span class="t_arg">T</span>, char[] <span class="t_arg">structname</span> = symbolnameof!(T));</code></p> 
     33<p><code>void wrap_struct(<span class="t_arg">T</span>, char[] <span class="t_arg">structname</span> = symbolnameof!(T), <span class="t_arg">Params</span>...) ();</code></p> 
    3434    <ul> 
    3535    <li><span class="t_arg">T</span> is the struct being wrapped.</li> 
    3636    <li><span class="t_arg">structname</span> is the name of the struct as it will appear in Python.</li> 
     37    <li><span class="t_arg">Params</span> is a series of struct types (defined below), which define the various members of the struct.</li> 
    3738    </ul> 
    3839 
    39 <p>To expose the data members, member functions, and properties of the class, <code>wrapped_struct</code> provides a series of template member functions.</p> 
     40<p>As with calls to <a href="class_wrapping.html"><code>wrap_class</code></a>, calls to <code>wrap_struct</code> must occur <em>after</em> calling <code>module_init</code>.</p> 
     41 
     42<p>To expose the data members, member functions, and properties of the struct, you must pass a series of struct template instantiations to <code>wrap_struct</code>.</p> 
    4043 
    4144<dl> 
    42 <dt><code>static void member(<span class="t_arg">M</span>, size_t <span class="t_arg">offset</span>, char[] <span class="t_arg">name</span>) (char[] <span class="arg">docstring</span>="");</code></dt> 
    43 <dd>This exposes a data member of the struct to Python. <span class="t_arg">M</span> is the type of the member, and must be a <a href="conversion.html">convertible type</a>. <span class="t_arg">offset</span> is the offset (in bytes) of the member in the struct. <span class="t_arg">name</span> is the name of the data member as it will be used in Python. <i>(Optimally, one would simply be able to pass an alias to the member, or at worst an alias and a name, but DMD currently has some issues with this.)</i></dd> 
     45<dt><code>struct Member(char[] <span class="t_arg">realname</span>, char[] <span class="t_arg">name</span>=realname);</code></dt> 
     46<dd>This exposes a data member of the struct to Python. The member must be a <a href="conversion.html">convertible type</a>. The <span class="t_arg">realname</span> is the member's actual name. <span class="t_arg">name</span> is the name of the data member as it will be used in Python. This defaults to <span class="t_arg">realname</span>.</dd> 
    4447 
    45 <dt><code>static void def(alias <span class="t_arg">fn</span>, char[] <span class="t_arg">name</span> = symbolnameof!(fn), <span class="t_arg">fn_t</span> = typeof(&amp;fn)) (char[] <span class="arg">docstring</span>="");</code></dt> 
    46 <dd>This wraps a member function of the struct. It functions exactly like the <code>def</code> function used to <a href="class_wrapping.html">wrap class methods</a>, including the lack of support for default arguments.</dd> 
     48<dt><code>struct Def(alias <span class="t_arg">fn</span>, char[] <span class="t_arg">name</span> = symbolnameof!(fn), <span class="t_arg">fn_t</span> = typeof(&amp;fn));</code></dt> 
     49<dd>This wraps a member function of the struct. It is in fact exactly the same <code>Def</code> struct template used to <a href="class_wrapping.html">wrap class methods</a>, including the lack of support for default arguments.</dd> 
    4750 
    48 <dt><code>static void static_def(alias <span class="t_arg">fn</span>, char[] <span class="t_arg">name</span> = symbolnameof!(fn), <span class="t_arg">fn_t</span> = typeof(&amp;fn), uint <span class="t_arg">MIN_ARGS</span> = minArgs!(fn)) (char[] <span class="arg">docstring</span>="");</code></dt> 
    49 <dd>This wraps a static member function of the struct. It functions exactly like the <code>static_def</code> function used to wrap static class member functions, and also includes support for default arguments.</dd> 
     51<dt><code>struct StaticDef(alias <span class="t_arg">fn</span>, char[] <span class="t_arg">name</span> = symbolnameof!(fn), <span class="t_arg">fn_t</span> = typeof(&amp;fn), uint <span class="t_arg">MIN_ARGS</span> = minArgs!(fn));</code></dt> 
     52<dd>This wraps a static member function of the struct. It is the same <code>StaticDef</code> struct template used to wrap static class member functions, and also includes support for default arguments.</dd> 
    5053 
    51 <dt><code>static void prop(alias <span class="t_arg">fn</span>, char[] <span class="t_arg">name</span> = symbolnameof!(fn), bool <span class="t_arg">RO</span> = false) (char[] <span class="arg">docstring</span>="");</code></dt> 
    52 <dd>This wraps a property. It is identical to the <code>prop</code> function used to <a href="class_wrapping.html">wrap class properties</a>.</dd> 
     54<dt><code>struct Property(alias <span class="t_arg">fn</span>, char[] <span class="t_arg">name</span> = symbolnameof!(fn), bool <span class="t_arg">RO</span> = false);</code></dt> 
     55<dd>This wraps a property. It is the same <code>Property</code> struct template used to <a href="class_wrapping.html">wrap class properties</a>.</dd> 
    5356 
    54 <dt><code>static void iter(<span class="t_arg">iter_t</span>) ();</code></dt> 
    55 <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.) It is identical to the <code>iter</code> function used in <a href="class_wrapping.html">class wrapping</a>.</dd> 
     57<dt><code>struct Iter(<span class="t_arg">iter_t</span>);</code></dt> 
     58<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.) It is the same <code>Iter</code> struct template used in <a href="class_wrapping.html">class wrapping</a>.</dd> 
    5659 
    57 <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>) (char[] <span class="arg">docstring</span>="");</code></dt> 
    58 <dd>This wraps alternate iterator methods as Python methods that return iterator objects. It is is identical to the <code>alt_iter</code> function used in <a href="class_wrapping.html">class wrapping</a>.</dd> 
     60<dt><code>struct AltIter(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> 
     61<dd>This wraps alternate iterator methods as Python methods that return iterator objects. It is the same <code>AltIter</code> struct template used in <a href="class_wrapping.html">class wrapping</a>.</dd> 
    5962</dl> 
    6063 
    61 <p><i>(Future enhancements: Support for struct ctors.)</i></p> 
    62  
    63 <p>Once you have called all of the member functions of <code>wrapped_struct</code> that you wish to, you must issue a call to <code>finalize_struct</code>.</p> 
    64  
    65 <p><code>void finalize_struct(<span class="t_arg">S</span>) (<span class="t_arg">S</span> <span class="arg">s</span>, char[] <span class="arg">docstring</span>="");</code></p> 
    66  
    67 <p>This does some final initialization of the type and then registers it with Python. As with calls to <a href="class_wrapping.html"><code>finalize_class</code></a>, calls to <code>finalize_struct</code> must occur <em>after</em> calling <code>module_init</code>. The <span class="arg">s</span> function argument should be an instance of <code>wrapped_struct</code>.</p> 
     64<!--<p><i>(Future enhancements: Support for struct ctors.)</i></p>--> 
    6865 
    6966<p>The <code>is_wrapped</code> template is available for wrapped structs, just like it is for wrapped classes.</p> 
     
    7572<p>Support for operator overloading in structs is identical to that available for classes.</p> 
    7673 
     74<h3><a class="anchor" name="inherit">Inheritance</a></h3> 
     75 
     76<p>D does not support struct inheritance. Therefore, Pyd does not provide any support for struct inheritance. However, the Python type wrapping the D struct can be subclassed from within Python. Users should not expect polymorphic behavior if they attempt to pass instances of any subclasses back to D.</p> 
     77 
    7778<h3><a class="anchor" name="examples">Examples</a></h3> 
    7879 
  • trunk/raw_html/basics.html

    r64 r102  
    3535<p>It does little more than call <a href="http://docs.python.org/api/allocating-objects.html">Py_InitModule</a> and return the new module object. This object is also available via the <code>Pyd_Module_p</code> property once you've called <code>module_init</code>.</p> 
    3636 
    37 <p>Due to the way in which Pyd implements function and class wrapping, any calls to <code>def</code> must occur <em>before</em> the call to <code>module_init</code>, and any calls to <code>finalize_class</code> must occur <em>after</em> the call. I know this seems like a rather arbitrary rule, but it is important. Calls to <code>def</code> in the wrong place will simply be ignored, and calls to <code>finalize_class</code> in the wrong place will throw an assert.</p> 
     37<p>Due to the way in which Pyd implements function and class wrapping, any calls to <code>def</code> must occur <em>before</em> the call to <code>module_init</code>, and any calls to <code>wrap_class</code> must occur <em>after</em> the call. I know this seems like a rather arbitrary rule, but it is important. Calls to <code>def</code> in the wrong place will simply be ignored, and calls to <code>wrap_class</code> in the wrong place will throw an assert.</p> 
    3838 
    3939<p><code>PydMain</code> will catch any D exception that is thrown from inside it, and <a href="except_wrapping.html">safely pass that exception to Python</a>.</p> 
  • trunk/raw_html/celerid.html

    r64 r102  
    4242    <dt><code>raw_only</code></dt> <dd>This flag defaults to <code>False</code>. When <code>True</code>, it supresses the compilation and linkage of Pyd, StackThreads, and meta. This is useful if you only want to write a raw Python/C extension without the overhead of Pyd and its auxiliary packages. This is equivalent to specifying <code>False</code> to the next four flags.</dd> 
    4343    <dt><code>with_pyd</code></dt> <dd>This flag defaults to <code>True</code>. When <code>False</code>, it supresses the compilation and linkage of Pyd. This is useful if you want to write a raw Python/C extension and don't want the overhead of compiling Pyd.</dd> 
    44     <dt><code>with_st</code></dt> <dd>This flag defaults to <code>True</code>. When <code>False</code>, it supresses the compilation and linkage of StackThreads. Pyd uses StackThreads for its iteration wrapping support. By setting this to <code>False</code>, opApply wrapping, <code>wrapped_class.iter</code>, and <code>wrapped_class.alt_iter</code> will be unavailable. If <code>with_pyd</code> and this are <code>True</code>, then the <code>Pyd_with_StackThreads</code> version flag will be defined (which is used internally by Pyd). <b>Important note:</b> StackThreads does not currently work with GDC! CeleriD will always set this flag to <code>False</code> when using GDC! This means that opApply wrapping is not available on Linux at this time.</dd> 
     44    <dt><code>with_st</code></dt> <dd>This flag defaults to <code>True</code>. When <code>False</code>, it supresses the compilation and linkage of StackThreads. Pyd uses StackThreads for its iteration wrapping support. By setting this to <code>False</code>, opApply wrapping, <code>Iter</code>, and <code>AltIter</code> will be unavailable. If <code>with_pyd</code> and this are <code>True</code>, then the <code>Pyd_with_StackThreads</code> version flag will be defined (which is used internally by Pyd). <b>Important note:</b> StackThreads does not currently work with GDC! CeleriD will always set this flag to <code>False</code> when using GDC! This means that opApply wrapping is not available on Linux at this time.</dd> 
    4545    <dt><code>with_meta</code></dt> <dd>This flag defaults to <code>True</code>. When <code>False</code>, it supresses the compilation and linkage of <code>meta</code> (Pyd's metaprogramming package). Because Pyd depends on meta, an exception will be raised if <code>with_pyd</code> is <code>True</code> and this is not.</dd> 
    4646    <dt><code>with_main</code></dt> <dd>This flag defaults to <code>True</code>. When <code>False</code>, it supresses the use of the "magic" <code>PydMain</code> function. (Instead, users must manually declare a C-style <code>init</code> function.) Do not use this unless you know what you are doing. If <code>with_pyd</code> is <code>False</code>, this will silently be set to <code>False</code> as well. <code>PydMain</code> can only be used if Pyd itself is in use.</dd> 
  • trunk/raw_html/class_wrapping.html

    r91 r102  
    1313<h1>Class wrapping</h1> 
    1414 
    15 <p>Exposing D classes to Python is easy! The heart of Pyd's class wrapping features is the <code>wrapped_class</code> template struct:</p> 
     15<p>Exposing D classes to Python is easy! The heart of Pyd's class wrapping features is the <code>wrap_class</code> function template:</p> 
    1616 
    17 <p><code>struct wrapped_class(<span class="t_arg">T</span>, char[] <span class="t_arg">classname</span> = symbolnameof!(T));</code></p> 
     17<p><code>void wrap_class(<span class="t_arg">T</span>, char[] <span class="t_arg">classname</span> = symbolnameof!(T), <span class="t_arg">Params</span>...) ();</code></p> 
    1818    <ul> 
    1919    <li><span class="t_arg">T</span> is the class being wrapped.</li> 
    20     <li><span class="t_arg">classname</span> is the name of the class as it will appear in Python.</li> 
     20    <li><span class="t_arg">classname</span> is the name of the class as it will appear in Python. It defaults to the name of the D class. If you are wrapping an instance of a class template, you will have to provide this explicitly.</li> 
     21    <li><span class="t_arg">Params</span> is a series of struct types (defined below), which define the various members of the class.</li> 
    2122    </ul> 
    2223 
    23 <p>To expose the constructors, methods, and properties of the class, <code>wrapped_class</code> provides a series of template member functions.</p> 
     24<p>Calls to <code>wrap_class</code> must occur <em>after</em> calling <code>module_init</code>.</p> 
     25 
     26<p>To expose the constructors, methods, and properties of the class, you must pass <code>wrap_class</code> instantiations of these struct templates.</p> 
    2427 
    2528<dl> 
    26 <dt><code>static void def(alias <span class="t_arg">fn</span>, char[] <span class="t_arg">name</span> = symbolnameof!(fn), <span class="t_arg">fn_t</span> = typeof(&amp;fn)) (char[] <span class="arg">docstring</span>="");</code></dt> 
    27 <dd>This wraps a method of the class. It functions exactly like the <code>def</code> function used to <a href="func_wrapping.html">wrap regular functions</a>, with one very important difference: There is no support for default arguments. (This is a side-effect of the fact that you cannot call an alias of a method in D, and delegates do not understand default arguments.)</dd> 
     29<dt><code>struct Def(alias <span class="t_arg">fn</span>, char[] <span class="t_arg">name</span> = symbolnameof!(fn), <span class="t_arg">fn_t</span> = typeof(&amp;fn));</code></dt> 
     30<dd>This wraps a method of the class. It functions very much like the <code>def</code> function used to <a href="func_wrapping.html">wrap regular functions</a>, with one very important difference: There is no support for default arguments. (This is a side-effect of the fact that you cannot call an alias of a method in D, and delegates do not understand default arguments.)</dd> 
    2831 
    29 <dt><code>static void static_def(alias <span class="t_arg">fn</span>, char[] <span class="t_arg">name</span> = symbolnameof!(fn), <span class="t_arg">fn_t</span> = typeof(&amp;fn), uint <span class="t_arg">MIN_ARGS</span> = minArgs!(fn)) (char[] <span class="arg">docstring</span>="");</code></dt> 
     32<dt><code>struct StaticDef(alias <span class="t_arg">fn</span>, char[] <span class="t_arg">name</span> = symbolnameof!(fn), <span class="t_arg">fn_t</span> = typeof(&amp;fn), uint <span class="t_arg">MIN_ARGS</span> = minArgs!(fn));</code></dt> 
    3033<dd>This wraps a static member function of the class. It also functions exactly like the <code>def</code> function used to wrap regular functions, and even includes support for default arguments.</dd> 
    3134 
    32 <dt><code>static void prop(alias <span class="t_arg">fn</span>, char[] <span class="t_arg">name</span> = symbolnameof!(fn), bool <span class="t_arg">RO</span> = false) (char[] <span class="arg">docstring</span>="");</code></dt> 
     35<dt><code>struct Property(alias <span class="t_arg">fn</span>, char[] <span class="t_arg">name</span> = symbolnameof!(fn), bool <span class="t_arg">RO</span> = false);</code></dt> 
    3336<dd>This wraps a property. See the examples below for more details. 
    3437    <ul> 
     
    3639    <li><span class="t_arg">name</span> is the name of the property as it will appear in Python. As with <code>def</code>, <code>prop</code> will attempt to derive this automatically.</li> 
    3740    <li><span class="t_arg">RO</span> specifies whether this is a <i>read-only</i> property. If true, it will only wrap the "get" form of the property. If false, it will wrap both the "get" and "set" forms. <i>(This is a little hackish, and I will probably try to make this detection more automatic in the future. It also means it cannot support a property that only has a "set" form.)</i></li> 
    38     <li><span class="arg">docstring</span> is the property's docstring. As usual, note that this is a regular function argument, and not a template argument.</li> 
    3941    </ul> 
    4042</dd> 
    4143 
    42 <dt><code>static void init(<span class="t_arg">C</span> ...) ();</code></dt> 
    43 <dd>This allows you to expose the class's constructors to Python. If the class provides a zero-argument constructor, there is no need to specify it; it is always available. Each element of <span class="t_arg">C</span> should be a function type. Each function type should correspond to a constructor. (That is, the arguments to the function should be the same as arguments to the class constructor. The return type is ignored.) There is an additional limitation at this time: No two constructors may have the same number of arguments. Pyd will always attempt to call the first constructor with the right number of arguments. If you wish to support a constructor with default arguments, you must specify each possible constructor call as a different template argument to this function. The examples show a few uses of the <code>init</code> function.</dd> 
     44<dt><code>struct Init(<span class="t_arg">C</span> ...);</code></dt> 
     45<dd>This allows you to expose the class's constructors to Python. If the class provides a zero-argument constructor, there is no need to specify it; it is always available. Each element of <span class="t_arg">C</span> should be a function type. Each function type should correspond to a constructor. (That is, the arguments to the function type should be the same as the arguments to the class constructor. The return type is ignored.) There is an additional limitation at this time: No two constructors may have the same number of arguments. Pyd will always attempt to call the first constructor with the right number of arguments. If you wish to support a constructor with default arguments, you must specify each possible constructor call as a different template argument to this function. The examples show a few uses of the <code>init</code> function.</dd> 
    4446 
    45 <dt><code>static void parent(<span class="t_arg">Parent</span>) ();</code></dt> 
    46 <dd>This allows the user to manually specify a class as this class's parent. This is intended for a very specific purpose (related to how Pyd handles <a href="inherit.html">inheritance</a>), and should not be used heedlessly. If a class's parent was previously wrapped, then Pyd will detect this and set up a parent-child relationship automatically, in which case it is not neccessary to specify this.</dd> 
    47  
    48 <dt><code>static void hide();</code></dt> 
    49 <dd>Causes this class to be wrapped, but not actually directly exposed to Python. This can be useful if you want to return instances of a class without allowing Python code to instantiate them. This is mainly used when handling <a href="inherit.html">inheritance</a>.</dd> 
    50  
    51 <dt><code>static void iter(<span class="t_arg">iter_t</span>) ();</code></dt> 
     47<dt><code>struct Iter(<span class="t_arg">iter_t</span>);</code></dt> 
    5248<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! (This is not available in Linux; see the note below on opApply wrapping.)</dd> 
    5349 
    54 <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>) (char[] <span class="arg">docstring</span>="");</code></dt> 
     50<dt><code>struct AltIter(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> 
    5551<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. (This is not available in Linux; see the note below on opApply wrapping.) 
    5652</dd> 
    5753</dl> 
    58  
    59 <p>Once you have called all of the member functions of <code>wrapped_class</code> that you wish to, you must issue a call to <code>finalize_class</code>.</p> 
    60  
    61 <p><code>void finalize_class(<span class="t_arg">CLS</span>) (<span class="t_arg">CLS</span> <span class="arg">cls</span>, char[] <span class="arg">docstring</span>="");</code></p> 
    62  
    63 <p>This does some final initialization of the class and then registers it with Python. Unlike calls to <a href="func_wrapping.html"><code>def</code></a>, calls to <code>finalize_class</code> must occur <em>after</em> calling <code>module_init</code>. The <span class="arg">cls</span> function argument should be an instance of <code>wrapped_class</code>.</p> 
    6454 
    6555<p>If you ever wish to check whether a given class has been wrapped, Pyd helpfully registers all wrapped classes with the <code>is_wrapped</code> template, which is just a templated <code>bool</code>:</p> 
     
    8070<p>At the moment, only the following operator overloads are supported:</p> 
    8171 
    82 <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> 
     72<p><code>opNeg, opPos, opCom, 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> 
    8373 
    84 <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> 
     74<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>Def</code>, of course.) Also missing from the list is <code>opApplyReverse</code>. This must be wrapped explicitly with <code>AltIter</code>.</p> 
    8575 
    8676<p>Also missing from the list is <code>opAssign</code>. Python has strict reference semantics for its objects, so overloading the assignment operator is not possible. You must explicitly wrap <code>opAssign</code> with a regular method.</p> 
    8777 
    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> and the special <code>__len__</code> method. 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> 
     78<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> and the special <code>__len__</code> method. You may still wrap it with <code>Property</code> or <code>Def</code> if you wish it to be available as a normal property or method.</p> 
    8979 
    9080<p><b>Notes on wrapped operators</b></p> 
     
    124114<p>We would expose this class to Python by putting this code in <code>PydMain</code> after the call to <code>module_init</code>:</p> 
    125115 
    126 <pre class="code"><span class="comment">// Make an instance of wrapped_class</span> 
    127 wrapped_class!(Foo) f; 
    128 <span class="comment">// Wrap the "foo" method</span> 
    129 f.def!(Foo.foo); 
    130 <span class="comment">// Wrap the "i" property</span> 
    131 f.prop!(Foo.i); 
    132 <span class="comment">// Wrap the constructors.</span> 
    133 f.init!(<span class="keyword">void function</span>(<span class="keyword">int</span>), <span class="keyword">void function</span>(<span class="keyword">int</span>, <span class="keyword">int</span>)); 
    134 finalize_class(f);</pre> 
     116<pre class="code"><span class="comment">// Call wrap_class</span> 
     117wrap_class!( 
     118    Foo, 
     119    <span class="comment">// Wrap the "foo" method</span> 
     120    Def!(Foo.foo), 
     121    <span class="comment">// Wrap the "i" property</span> 
     122    Property!(Foo.i), 
     123    <span class="comment">// Wrap the constructors.</span> 
     124    Init!(<span class="keyword">void function</span>(<span class="keyword">int</span>), <span class="keyword">void function</span>(<span class="keyword">int</span>, <span class="keyword">int</span>)) 
     125);</pre> 
    135126 
    136127<p>Now we can use this type from within Python like any other type.</p> 
    137128 
    138 <pre class="code">&gt;&gt;&gt; from testmodule import Foo 
     129<pre class="code">&gt;&gt;&gt; <span class="keyword">from</span> testmodule <span class="keyword">import</span> Foo 
    139130&gt;&gt;&gt; f = Foo() 
    140131&gt;&gt;&gt; f.i 
    1411320 
    142133&gt;&gt;&gt; f.i = 20 
    143 &gt;&gt;&gt; f.foo("Hello! i is "
     134&gt;&gt;&gt; f.foo(<span class="string">"Hello! i is "</span>
    144135Hello! i is 20 
    145136&gt;&gt;&gt; f = Foo(10, 10) 
     
    152143&gt;&gt;&gt; e.i 
    15314450 
    154 &gt;&gt;&gt; # We can even subclass our D type 
    155 &gt;&gt;&gt; class MyFoo(Foo): 
    156 ...     def bar(self): 
    157 ...         print "Hey, i+3 is", self.i + 3 
     145&gt;&gt;&gt; <span class="comment"># We can even subclass our D type</span> 
     146&gt;&gt;&gt; <span class="keyword">class</span> MyFoo(Foo): 
     147...     <span class="keyword">def</span> bar(self): 
     148...         <span class="keyword">print</span> <span class="string">"Hey, i+3 is"</span>, self.i + 3 
    158149...  
    159150&gt;&gt;&gt; h = MyFoo(3) 
  • trunk/raw_html/inherit.html

    r91 r102  
    2828<p>These would be exposed to Python by putting this code in <code>PydMain</code> after the call to <code>module_init</code>:</p> 
    2929 
    30 <pre class="code">wrapped_class!(Base) b; 
    31 b.def!(Base.foo); 
    32 b.def!(Base.bar); 
    33 finalize_class(b); 
     30<pre class="code">wrap_class!( 
     31    Base, 
     32    Def!(Base.foo), 
     33    Def!(Base.bar), 
     34); 
    3435 
    35 wrapped_class!(Derived) d; 
    36 d.def!(Derived.foo); 
    37 finalize_class(d);</pre> 
     36wrap_class!( 
     37    Derived, 
     38    Def!(Derived.foo), 
     39);</pre> 
    3840 
    3941<p>When used in Python, we get the expected behavior:</p> 
     
    5254Base.bar</pre> 
    5355 
    54 <p>There is one weakness in the default behavior. Take a function like the following:</p> 
     56<p>Polymorphic behavior is also automatically taken care of. Take a function like the following:</p> 
    5557 
    5658<pre class="code"><span class="keyword">void</span> polymorphic_call(Base b) { 
     
    6062<p>And in Python:</p> 
    6163 
    62 <pre class="code"><span class="keyword">class</span> PyClass(Base): 
    63     <span class="keyword">def</span> foo(self): 
    64         <span class="keyword">print</span> <span class="string">"PyClass.foo"</span> 
    65  
     64<pre class="code">&gt;&gt;&gt; <span class="keyword">class</span> PyClass(Base): 
     65...    <span class="keyword">def</span> foo(self): 
     66...        <span class="keyword">print</span> <span class="string">"PyClass.foo"</span> 
     67...  
    6668&gt;&gt;&gt; p = PyClass() 
    6769&gt;&gt;&gt; polymorphic_call(p) 
    68 Base.foo</pre> 
    69  
    70 <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> 
    71  
    72 <pre class="code"><span class="keyword">class</span> BaseWrap : Base { 
    73     <span class="keyword">mixin</span> OverloadShim; 
    74     <span class="keyword">void</span> foo() { 
    75         get_overload(&amp;<span class="keyword">super</span>.foo, <span class="string">"foo"</span>); 
    76     } 
    77     <span class="keyword">void</span> bar() { 
    78         get_overload(&amp;<span class="keyword">super</span>.bar, <span class="string">"bar"</span>); 
    79     } 
    80 }</pre> 
    81  
    82 <p>The <code>OverloadShim</code> template has but a single member, the <code>get_overload</code> function.</p> 
    83  
    84 <dl> 
    85 <dt><code>ReturnType!(dg_t) get_overload(<span class="t_arg">dg_t</span>, <span class="t_arg">T ...</span>) (dg_t <span class="arg">dg</span>, char[] <span class="arg">name</span>, T <span class="arg">t</span>);</code></dt> 
    86 <dd><ul> 
    87     <li><span class="arg">dg</span> should be a delegate to the parent class's method.</li> 
    88     <li><span class="arg">name</span> should be the name of the method as Python understands it to be. <i>(There's no efficient way to derive this automatically based on only the delegate.)</i></li> 
    89     <li><span class="arg">t</span> is a tuple argument. These arguments will be passed on to the actual function call, be it the parent class's implementation or a Python subclass's implementation.</li> 
    90 </ul></dd> 
    91 </dl> 
    92  
    93 <p><code>get_overload</code> returns whatever the method does.</p> 
    94  
    95 <p>Now, we must replace the old wrapping of Base with this:</p> 
    96  
    97 <pre class="code">wrapped_class!(BaseWrap, <span class="string">"Base"</span>) w; 
    98 w.def!(BaseWrap.foo); 
    99 w.def!(BaseWrap.bar); 
    100 finalize_class(w);</pre> 
    101  
    102 <p>Now our subclass will perform just like we expect:</p> 
    103  
    104 <pre class="code">&gt;&gt;&gt; p = PyClass() 
    105 &gt;&gt;&gt; polymorphic_call(p) 
    10670PyClass.foo</pre> 
    107  
    108 <p>However, BaseWrap has no particular relationship to Derived. You may remember that Derived overloads <tt>bar</tt> but not <tt>foo</tt>. When we wrapped Derived in <tt>PydMain</tt>, we specified the <tt>foo</tt> overload but not the <tt>bar</tt> overload. Because Derived's parent class is no longer wrapped, Pyd no longer has any way to know about the <tt>bar</tt> method of the Derived class.</tt></p> 
    109  
    110 <p>The solution is to explicitly tell Pyd that Derived's parent is BaseWrap. Furthermore, it is probably best to go the extra mile, by wrapping an <tt>OverloadShim</tt> subclass of Derived (call it DerivedWrap), and telling Pyd that BaseWrap is <em>its</em> parent. Additionally, the original <tt>Base</tt> and <tt>Derived</tt> classes should still be wrapped, in the event that functions return instances of them to Python, but should not actually be exposed to Python. The complete solution ends up looking like this:</p> 
    111  
    112 <pre class="code"><span class="keyword">import</span> pyd.pyd; 
    113 <span class="keyword">import