Changeset 45
- Timestamp:
- 11/19/06 20:08:43 (1 year ago)
- Files:
-
- trunk/dcompiler.py (modified) (6 diffs)
- trunk/examples/testdll/testdll.d (modified) (3 diffs)
- trunk/html_doc/basics.html (modified) (4 diffs)
- trunk/html_doc/celerid.html (modified) (2 diffs)
- trunk/html_doc/class_wrapping.html (modified) (3 diffs)
- trunk/html_doc/conversion.html (modified) (2 diffs)
- trunk/html_doc/credits.html (added)
- trunk/html_doc/dpyobject.html (modified) (2 diffs)
- trunk/html_doc/except_wrapping.html (modified) (2 diffs)
- trunk/html_doc/func_wrapping.html (modified) (2 diffs)
- trunk/html_doc/index.html (modified) (3 diffs)
- trunk/html_doc/install.html (added)
- trunk/infrastructure/meta/Apply.d (deleted)
- trunk/infrastructure/meta/Bind.d (deleted)
- trunk/infrastructure/meta/Default.d (modified) (4 diffs)
- trunk/infrastructure/meta/FuncMeta.d (deleted)
- trunk/infrastructure/meta/Instantiate.d (deleted)
- trunk/infrastructure/meta/Tuple.d (deleted)
- trunk/infrastructure/meta/Use.d (deleted)
- trunk/infrastructure/meta/VarArg.d (deleted)
- trunk/infrastructure/pyd/class_wrap.d (modified) (13 diffs)
- trunk/infrastructure/pyd/ctor_wrap.d (modified) (3 diffs)
- trunk/infrastructure/pyd/def.d (modified) (1 diff)
- trunk/infrastructure/pyd/dg_convert.d (modified) (2 diffs)
- trunk/infrastructure/pyd/dpyobject.d (modified) (1 diff)
- trunk/infrastructure/pyd/func_wrap.d (modified) (13 diffs)
- trunk/infrastructure/pyd/iteration.d (modified) (4 diffs)
- trunk/infrastructure/pyd/make_object.d (modified) (3 diffs)
- trunk/infrastructure/pyd/op_wrap.d (modified) (20 diffs)
- trunk/infrastructure/pyd/pyd.d (modified) (1 diff)
- trunk/infrastructure/python/2.4 (added)
- trunk/infrastructure/python/2.4/python.d (added)
- trunk/infrastructure/python/2.4/python24_digitalmars.lib (added)
- trunk/infrastructure/python/2.5 (added)
- trunk/infrastructure/python/2.5/python.d (added)
- trunk/infrastructure/python/2.5/python25_digitalmars.lib (added)
- trunk/infrastructure/python/headers (deleted)
- trunk/infrastructure/python/libs (deleted)
- trunk/pydmdvars.bat (modified) (1 diff)
- trunk/setup.py (modified) (3 diffs)
- trunk/version.txt (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/dcompiler.py
r40 r45 32 32 'dpyobject.d', 33 33 'exception.d', 34 # 'ftype.d',35 34 'func_wrap.d', 36 35 'iteration.d', … … 38 37 'op_wrap.d', 39 38 'pyd.d', 40 # 'tuples.d',41 39 ] 42 40 … … 49 47 50 48 _metaFiles = [ 51 'Apply.d',52 'Bind.d',53 49 'Default.d', 54 50 'Demangle.d', 55 'FuncMeta.d',56 'Instantiate.d',57 51 'Nameof.d', 58 'Tuple.d',59 'Use.d',60 52 'Util.d', 61 'VarArg.d',62 53 ] 63 54 … … 153 144 # To sources, add the appropriate D header file python.d, as well as 154 145 # any platform-specific boilerplate. 155 pythonHeaderPath = os.path.join(_infraDir, 'python', 'headers', 'python.d')146 pythonHeaderPath = os.path.join(_infraDir, 'python', _pyVerXDotY, 'python.d') 156 147 # Add the python header's directory to the include path 157 148 includePathOpts += self._includeOpts 158 includePathOpts[-1] = includePathOpts[-1] % os.path.join(_infraDir, 'python', 'headers')149 includePathOpts[-1] = includePathOpts[-1] % os.path.join(_infraDir, 'python', _pyVerXDotY) 159 150 if not os.path.isfile(pythonHeaderPath): 160 151 raise DistutilsPlatformError('Required D translation of Python' … … 188 179 ) 189 180 sources.append(filePath) 190 # Add the infraDir to the include path for Pyd and ST181 # Add the infraDir to the include path for pyd, st, and meta. 191 182 includePathOpts += self._includeOpts 192 183 includePathOpts[-1] = includePathOpts[-1] % os.path.join(_infraDir) … … 451 442 # more convenient to distribute a pre-extracted .lib file to the 452 443 # users and spare them the need for the "Basic Utilities" package. 453 pythonDMDLibPath = _qp(os.path.join(_infraDir, 'python', 'libs',454 _pyVerXDotY,'python%s_digitalmars.lib' % _pyVerXY444 pythonDMDLibPath = _qp(os.path.join(_infraDir, 'python', _pyVerXDotY, 445 'python%s_digitalmars.lib' % _pyVerXY 455 446 )) 456 447 if not os.path.isfile(pythonDMDLibPath): trunk/examples/testdll/testdll.d
r44 r45 4 4 import pyd.pyd; 5 5 //import pyd.ftype; 6 import std.stdio ;6 import std.stdio, std.string; 7 7 8 import meta.Tuple;9 import meta.Apply;8 //import meta.Tuple; 9 //import meta.Apply; 10 10 11 11 void apply_test(int i, char[] s) { … … 14 14 15 15 void foo() { 16 /+ 16 17 alias Tuple!(int, char[]) T; 17 18 T t; … … 19 20 t.val!(1) = "Monkey"; 20 21 apply(&apply_test, t); 22 +/ 23 writefln("20 Monkey"); 21 24 } 22 25 trunk/html_doc/basics.html
r40 r45 11 11 <p><big>Contents</big></p> 12 12 <a class="nav" href="index.html">Main</a><br /> 13 <a class="nav" href="install.html">Installation</a><br /> 13 14 <a class="navcur" href="basics.html">The basics</a><br /> 14 15 <a class="nav" href="celerid.html">CeleriD</a><br /> … … 17 18 <a class="nav" href="class_wrapping.html">Class wrapping</a><br /> 18 19 <a class="nav" href="except_wrapping.html">Exception wrapping</a><br /> 19 <a class="nav" href="dpyobject.html">DPyObject</a> 20 <a class="nav" href="dpyobject.html">DPyObject</a><br /> 21 <a class="nav" href="credits.html">Credits</a> 20 22 </div> 21 23 … … 23 25 24 26 <h1>The basics</h1> 25 26 <h3>Installation and requirements</h3>27 28 <p>Pyd requires Python 2.4 or newer and the latest version of DMD.</p>29 30 <p>At the moment, Pyd is only supported on Windows using the <a href="http://digitalmars.com/d/index.html">DMD</a> compiler. GDC support has been written, but Pyd cannot yet be compiled with GDC (due to <a href="http://d.puremagic.com/issues/show_bug.cgi?id=311">this bug</a>). Once GDC support is available, Pyd should work on Linux. Support for Derek Parnell's Build is also planned.</p>31 32 <p>Because Pyd is still in development, it is only available via Subversion. The repository is located <a href="http://svn.dsource.org/projects/pyd/trunk">here</a>.</p>33 34 <p>Pyd installs itself as a Python package called <a href="celerid.html"><code>celerid</code></a>. Once you have downloaded the "trunk" directory, simply run <code>python setup.py install</code>, and the <code>celerid</code> directory will be created in Python's site-packages directory.</p>35 27 36 28 <h3>Module basics</h3> … … 60 52 61 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. (And this assert will cause the Python interpreter to crash. So be warned.)</p> 54 55 <p>It is important that no D exceptions escape from the init function. If you put any of your own code in the init function, be sure to guard it aginst exceptions. The <a href="except_wrapping.html">exception wrapping</a> facilities of Pyd provide some useful functions for this purpose.</p> 62 56 </div> 63 57 trunk/html_doc/celerid.html
r35 r45 11 11 <p><big>Contents</big></p> 12 12 <a class="nav" href="index.html">Main</a><br /> 13 <a class="nav" href="install.html">Installation</a><br /> 13 14 <a class="nav" href="basics.html">The basics</a><br /> 14 15 <a class="navcur" href="celerid.html">CeleriD</a><br /> … … 17 18 <a class="nav" href="class_wrapping.html">Class wrapping</a><br /> 18 19 <a class="nav" href="except_wrapping.html">Exception wrapping</a><br /> 19 <a class="nav" href="dpyobject.html">DPyObject</a> 20 <a class="nav" href="dpyobject.html">DPyObject</a><br /> 21 <a class="nav" href="credits.html">Credits</a> 20 22 </div> 21 23 trunk/html_doc/class_wrapping.html
r44 r45 11 11 <p><big>Contents</big></p> 12 12 <a class="nav" href="index.html">Main</a><br /> 13 <a class="nav" href="install.html">Installation</a><br /> 13 14 <a class="nav" href="basics.html">The basics</a><br /> 14 15 <a class="nav" href="celerid.html">CeleriD</a><br /> … … 17 18 <a class="navcur" href="class_wrapping.html">Class wrapping</a><br /> 18 19 <a class="nav" href="except_wrapping.html">Exception wrapping</a><br /> 19 <a class="nav" href="dpyobject.html">DPyObject</a> 20 <a class="nav" href="dpyobject.html">DPyObject</a><br /> 21 <a class="nav" href="credits.html">Credits</a> 20 22 </div> 21 23 … … 47 49 </dd> 48 50 49 <dt><code>static void init(<span class="t_arg">C 1</span>, <span class="t_arg">C2</span>, <span class="t_arg">C3</span>, ..., <span class="t_arg">C<i>n</i></span>) ();</code></dt>50 <dd>This allows you to expose anywhere from zero to 10 of 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 of <span class="t_arg">C<i>n</i></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>51 <dt><code>static void init(<span class="t_arg">C</span> ...) ();</code></dt> 52 <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> 51 53 52 54 <dt><code>static void iter(<span class="t_arg">iter_t</span>) ();</code></dt> trunk/html_doc/conversion.html
r35 r45 11 11 <p><big>Contents</big></p> 12 12 <a class="nav" href="index.html">Main</a><br /> 13 <a class="nav" href="install.html">Installation</a><br /> 13 14 <a class="nav" href="basics.html">The basics</a><br /> 14 15 <a class="nav" href="celerid.html">CeleriD</a><br /> … … 17 18 <a class="nav" href="class_wrapping.html">Class wrapping</a><br /> 18 19 <a class="nav" href="except_wrapping.html">Exception wrapping</a><br /> 19 <a class="nav" href="dpyobject.html">DPyObject</a> 20 <a class="nav" href="dpyobject.html">DPyObject</a><br /> 21 <a class="nav" href="credits.html">Credits</a> 20 22 </div> 21 23 trunk/html_doc/dpyobject.html
r35 r45 11 11 <p><big>Contents</big></p> 12 12 <a class="nav" href="index.html">Main</a><br /> 13 <a class="nav" href="install.html">Installation</a><br /> 13 14 <a class="nav" href="basics.html">The basics</a><br /> 14 15 <a class="nav" href="celerid.html">CeleriD</a><br /> … … 17 18 <a class="nav" href="class_wrapping.html">Class wrapping</a><br /> 18 19 <a class="nav" href="except_wrapping.html">Exception wrapping</a><br /> 19 <a class="navcur" href="dpyobject.html">DPyObject</a> 20 <a class="navcur" href="dpyobject.html">DPyObject</a><br /> 21 <a class="nav" href="credits.html">Credits</a> 20 22 </div> 21 23 trunk/html_doc/except_wrapping.html
r35 r45 11 11 <p><big>Contents</big></p> 12 12 <a class="nav" href="index.html">Main</a><br /> 13 <a class="nav" href="install.html">Installation</a><br /> 13 14 <a class="nav" href="basics.html">The basics</a><br /> 14 15 <a class="nav" href="celerid.html">CeleriD</a><br /> … … 17 18 <a class="nav" href="class_wrapping.html">Class wrapping</a><br /> 18 19 <a class="navcur" href="except_wrapping.html">Exception wrapping</a><br /> 19 <a class="nav" href="dpyobject.html">DPyObject</a> 20 <a class="nav" href="dpyobject.html">DPyObject</a><br /> 21 <a class="nav" href="credits.html">Credits</a> 20 22 </div> 21 23 trunk/html_doc/func_wrapping.html
r41 r45 11 11 <p><big>Contents</big></p> 12 12 <a class="nav" href="index.html">Main</a><br /> 13 <a class="nav" href="install.html">Installation</a><br /> 13 14 <a class="nav" href="basics.html">The basics</a><br /> 14 15 <a class="nav" href="celerid.html">CeleriD</a><br /> … … 17 18 <a class="nav" href="class_wrapping.html">Class wrapping</a><br /> 18 19 <a class="nav" href="except_wrapping.html">Exception wrapping</a><br /> 19 <a class="nav" href="dpyobject.html">DPyObject</a> 20 <a class="nav" href="dpyobject.html">DPyObject</a><br /> 21 <a class="nav" href="credits.html">Credits</a> 20 22 </div> 21 23 trunk/html_doc/index.html
r44 r45 11 11 <p><big>Contents</big></p> 12 12 <a class="navcur" href="index.html">Main</a><br /> 13 <a class="nav" href="install.html">Installation</a><br /> 13 14 <a class="nav" href="basics.html">The basics</a><br /> 14 15 <a class="nav" href="celerid.html">CeleriD</a><br /> … … 17 18 <a class="nav" href="class_wrapping.html">Class wrapping</a><br /> 18 19 <a class="nav" href="except_wrapping.html">Exception wrapping</a><br /> 19 <a class="nav" href="dpyobject.html">DPyObject</a> 20 <a class="nav" href="dpyobject.html">DPyObject</a><br /> 21 <a class="nav" href="credits.html">Credits</a> 20 22 </div> 21 23 … … 23 25 24 26 <h1>Pyd</h1> 25 <p>Pyd is a library for the D programming language that wraps the raw <a href="http://docs.python.org/api/api.html">Python/C API</a> with a cleaner, simpler interface. It makes exposing raw D functions and classes to Python almost trivially simple. It bears certain similarities to <a href="http://www.boost.org/libs/python/doc/">Boost.Python</a>, and indeed Boost.Python is a major influence on Pyd. </p>27 <p>Pyd is a library for the D programming language that wraps the raw <a href="http://docs.python.org/api/api.html">Python/C API</a> with a cleaner, simpler interface. It makes exposing raw D functions and classes to Python almost trivially simple. It bears certain similarities to <a href="http://www.boost.org/libs/python/doc/">Boost.Python</a>, and indeed Boost.Python is a major influence on Pyd. Pyd was written by Kirk McDonald.</p> 26 28 27 <p>Pyd also comes with its own extension to Python's <a href="http://docs.python.org/dist/dist.html">distutils</a>, called <a href="celerid.html">CeleriD</a>, making the building of extension modules quite easy.</p> 29 <p>Pyd also comes with its own extension to Python's <a href="http://docs.python.org/dist/dist.html">distutils</a>, called <a href="celerid.html">CeleriD</a>, making the building of extension modules quite easy. CeleriD was originally written by David Rushby and is currently maintained by Kirk McDonald.</p> 30 31 <p>Pyd includes the <code>meta.Nameof</code> package by Don Clugston. The source files meta.Nameof and meta.Demangle are copyright © 2005-2006 Don Clugston.</p> 32 33 <!-- Not documented, yet. 34 <p>Pyd includes its own metaprogramming library, <code>meta</code>, which was written by Tomasz Stachowiak, Don Clugston, and Kirk McDonald. The <code>meta</code> library is documented <a href="meta/index.html">here</a>.</code> 35 --> 28 36 29 37 <p>Pyd's Trac page can be found <a href="http://dsource.org/projects/pyd/wiki">here</a>.</p> trunk/infrastructure/meta/Default.d
r40 r45 4 4 module meta.Default; 5 5 6 private import meta.FuncMeta; 7 private import meta.Tuple; 8 private import meta.Nameof; 9 private import meta.Util; 6 private import std.traits; 7 private import std.typetuple; 10 8 11 9 /** … … 17 15 18 16 template firstArgsT(alias fn, uint args, fn_t = typeof(&fn)) { 19 alias Ret Type!(fn_t) R;20 alias funcDelegInfoT!(fn_t) Info;17 alias ReturnType!(fn_t) R; 18 alias ParameterTypeTuple!(fn_t) T; 21 19 22 // Shortcut for ArgType 23 template A(uint a) { 24 // The -1 is pointless; it dates from a time the function 25 // metaprogramming module was 1-indexed for function arguments. 26 alias Info.Meta.ArgType!(a-1) A; 27 } 28 29 static if (args == 0) { 30 R func() { 31 return fn(); 32 } 33 } else static if (args == 1) { 34 R func(A!(1) a1) { 35 return fn(a1); 36 } 37 } else static if (args == 2) { 38 R func(A!(1) a1, A!(2) a2) { 39 return fn(a1, a2); 40 } 41 } else static if (args == 3) { 42 R func(A!(1) a1, A!(2) a2, A!(3) a3) { 43 return fn(a1, a2, a3); 44 } 45 } else static if (args == 4) { 46 R func(A!(1) a1, A!(2) a2, A!(3) a3, A!(4) a4) { 47 return fn(a1, a2, a3, a4); 48 } 49 } else static if (args == 5) { 50 R func(A!(1) a1, A!(2) a2, A!(3) a3, A!(4) a4, A!(5) a5) { 51 return fn(a1, a2, a3, a4, a5); 52 } 53 } else static if (args == 6) { 54 R func(A!(1) a1, A!(2) a2, A!(3) a3, A!(4) a4, A!(5) a5, A!(6) a6) { 55 return fn(a1, a2, a3, a4, a5, a6); 56 } 57 } else static if (args == 7) { 58 R func(A!(1) a1, A!(2) a2, A!(3) a3, A!(4) a4, A!(5) a5, A!(6) a6, A!(7) a7) { 59 return fn(a1, a2, a3, a4, a5, a6, a7); 60 } 61 } else static if (args == 8) { 62 R func(A!(1) a1, A!(2) a2, A!(3) a3, A!(4) a4, A!(5) a5, A!(6) a6, A!(7) a7, A!(8) a8) { 63 return fn(a1, a2, a3, a4, a5, a6, a7, a8); 64 } 65 } else static if (args == 9) { 66 R func(A!(1) a1, A!(2) a2, A!(3) a3, A!(4) a4, A!(5) a5, A!(6) a6, A!(7) a7, A!(8) a8, A!(9) a9) { 67 return fn(a1, a2, a3, a4, a5, a6, a7, a8, a9); 68 } 69 } else static if (args == 10) { 70 R func(A!(1) a1, A!(2) a2, A!(3) a3, A!(4) a4, A!(5) a5, A!(6) a6, A!(7) a7, A!(8) a8, A!(9) a9, A!(10) a10) { 71 return fn(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); 20 R func(T[0 .. args] t) { 21 static if (is(R == void)) { 22 fn(t); 23 return; 24 } else { 25 return fn(t); 72 26 } 73 27 } 74 28 } 75 29 76 template defaultsTupleT(alias fn, uint MIN_ARGS, fn_t = typeof(&fn), uint current=MIN_ARGS, T = EmptyTuple) {77 alias funcDelegInfoT!(fn_t) Meta;78 const uint MAX_ARGS = Meta.numArgs;30 template defaultsTupleT(alias fn, uint MIN_ARGS, fn_t = typeof(&fn), uint current=MIN_ARGS, T ...) { 31 alias ParameterTypeTuple!(fn_t) Tu; 32 const uint MAX_ARGS = Tu.length; 79 33 static if (current > MAX_ARGS) { 80 34 alias T type; 81 35 } else { 82 alias defaultsTupleT!(fn, MIN_ARGS, fn_t, current+1, T.mix.appendT!(typeof(&firstArgs!(fn, current, fn_t)))).type type; 83 } 84 } 85 86 void loop(alias fn, fn_t, uint i, T)(T* t) { 87 static if (i < T.length) { 88 const uint args = funcDelegInfoT!(typeof(t.val!(i))).numArgs; 89 t.val!(i) = &firstArgs!(fn, args, fn_t); 90 loop!(fn, fn_t, i+1, T)(t); 36 alias defaultsTupleT!(fn, MIN_ARGS, fn_t, current+1, T, typeof(&firstArgs!(fn, current, fn_t))).type type; 91 37 } 92 38 } … … 96 42 calls to that function, as per its default arguments. 97 43 */ 98 defaultsTupleT!(fn, MIN_ARGS, fn_t).type defaultsTuple(alias fn, uint MIN_ARGS, fn_t = typeof(&fn)) () { 44 void defaultsTuple(alias fn, uint MIN_ARGS, fn_t = typeof(&fn)) ( 45 void delegate(defaultsTupleT!(fn, MIN_ARGS, fn_t).type) dg 46 ) { 99 47 alias defaultsTupleT!(fn, MIN_ARGS, fn_t).type T; 100 48 T t; 101 loop!(fn, fn_t, 0, T)(&t); 102 return t; 49 foreach(i, arg; t) { 50 t[i] = &firstArgs!(fn, ParameterTypeTuple!(typeof(t[i])).length, fn_t); 51 } 52 dg(t); 103 53 } 104 54 … … 125 75 126 76 template minArgsT(alias fn, fn_t = typeof(&fn)) { 127 alias funcDelegInfoT!(fn_t) Info;77 alias ParameterTypeTuple!(fn_t) T; 128 78 129 template A(uint i) { 130 alias Info.Meta.ArgType!(i) A; 131 } 132 133 A!(i) I(uint i)() { 134 return A!(i).init; 79 T[i] I(uint i)() { 80 return T[i].init; 135 81 } 136 82 trunk/infrastructure/pyd/class_wrap.d
r41 r45 34 34 35 35 import meta.Default; 36 import meta.FuncMeta;37 import meta.Tuple;38 36 import meta.Nameof; 39 37 40 38 import std.string; 39 import std.traits; 41 40 } 42 41 … … 61 60 /// The type object, an instance of PyType_Type 62 61 static PyTypeObject wrapped_class_type = { 63 1, 64 null, 62 1, /*ob_refcnt*/ 63 null, /*ob_type*/ 65 64 0, /*ob_size*/ 66 65 null, /*tp_name*/ … … 82 81 null, /*tp_setattro*/ 83 82 null, /*tp_as_buffer*/ 84 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/83 0, /*tp_flags*/ 85 84 null, /*tp_doc*/ 86 null, /* tp_traverse*/87 null, /* tp_clear*/88 null, /* tp_richcompare*/89 0, /* tp_weaklistoffset*/90 null, /* tp_iter*/91 null, /* tp_iternext*/92 null, /* tp_methods*/93 null, /* tp_members*/94 null, /* tp_getset*/95 null, /* tp_base*/96 null, /* tp_dict*/97 null, /* tp_descr_get*/98 null, /* tp_descr_set*/99 0, /* tp_dictoffset*/100 null, /* tp_init*/101 null, /* tp_alloc*/102 &wrapped_methods!(T).wrapped_new, /* tp_new*/103 null, /* tp_free*/104 null, /* tp_is_gc*/105 null, /* tp_bases*/106 null, /* tp_mro*/107 null, /* tp_cache*/108 null, /* tp_subclasses*/109 null, /* tp_weaklist*/110 null, /* tp_del*/85 null, /*tp_traverse*/ 86 null, /*tp_clear*/ 87 null, /*tp_richcompare*/ 88 0, /*tp_weaklistoffset*/ 89 null, /*tp_iter*/ 90 null, /*tp_iternext*/ 91 null, /*tp_methods*/ 92 null, /*tp_members*/ 93 null, /*tp_getset*/ 94 null, /*tp_base*/ 95 null, /*tp_dict*/ 96 null, /*tp_descr_get*/ 97 null, /*tp_descr_set*/ 98 0, /*tp_dictoffset*/ 99 null, /*tp_init*/ 100 null, /*tp_alloc*/ 101 &wrapped_methods!(T).wrapped_new, /*tp_new*/ 102 null, /*tp_free*/ 103 null, /*tp_is_gc*/ 104 null, /*tp_bases*/ 105 null, /*tp_mro*/ 106 null, /*tp_cache*/ 107 null, /*tp_subclasses*/ 108 null, /*tp_weaklist*/ 109 null, /*tp_del*/ 111 110 }; 112 111 } 112 113 // The set of all instances of this class that are passed into Python. Keeping 114 // references here in D is needed to keep the GC happy. The integer value is 115 // used to make this a sort of poor man's multiset. 116 template wrap_class_instances(T) { 117 int[T] wrap_class_instances; 118 } 119 120 /** 121 * A useful check for whether a given class has been wrapped. Mainly used by 122 * the conversion functions (see make_object.d), but possibly useful elsewhere. 123 */ 124 template is_wrapped(T) { 125 bool is_wrapped = false; 126 } 127 128 // The list of wrapped methods for this class. 129 template wrapped_method_list(T) { 130 PyMethodDef[] wrapped_method_list = [ 131 { null, null, 0, null } 132 ]; 133 } 134 135 // The list of wrapped properties for this class. 136 template wrapped_prop_list(T) { 137 static PyGetSetDef[] wrapped_prop_list = [ 138 { null, null, null, null, null } 139 ]; 140 } 141 142 ////////////////////// 143 // STANDARD METHODS // 144 ////////////////////// 113 145 114 146 /// Various wrapped methods … … 133 165 extern(C) 134 166 void wrapped_dealloc(PyObject* self) { 135 exception_catcher(delegate PyObject*() { 167 //exception_catcher(delegate PyObject*() { 168 try { 136 169 WrapPyObject_SetObj(self, null); 137 self.ob_type.tp_free(self); 138 return null; 139 }); 170 } catch { } 171 self.ob_type.tp_free(self); 172 return null; 173 //}); 140 174 } 141 175 } … … 154 188 } 155 189 156 ///157 template wrapped_init(T) {158 alias wrapped_class_object!(T) wrap_object;159 /// The default _init method calls the class's zero-argument constructor.160 extern(C)161 int init(PyObject* self, PyObject* args, PyObject* kwds) {162 return exception_catcher({163 WrapPyObject_SetObj(self, new T);164 return 0;165 });166 }167 }168 169 190 // This template gets an alias to a property and derives the types of the 170 191 // getter form and the setter form. It requires that the getter form return the … … 173 194 // This may be either the getter or the setter 174 195 alias typeof(&p) p_t; 175 alias funcDelegInfoT!(p_t) Info;196 alias ParameterTypeTuple!(p_t) Info; 176 197 // This means it's the getter 177 static if (Info. numArgs== 0) {198 static if (Info.length == 0) { 178 199 alias p_t getter_type; 179 200 // The setter may return void, or it may return the newly set attribute. 180 alias typeof(p(Ret Type!(p_t).init)) function(RetType!(p_t)) setter_type;201 alias typeof(p(ReturnType!(p_t).init)) function(ReturnType!(p_t)) setter_type; 181 202 // This means it's the setter 182 203 } else { 183 204 alias p_t setter_type; 184 alias Info .Meta.ArgType!(0)function() getter_type;205 alias Info[0] function() getter_type; 185 206 } 186 207 } … … 216 237 } 217 238 218 // The set of all instances of this class that are passed into Python. Keeping 219 // references here in D is needed to keep the GC happy. The integer value is 220 // used to make this a sort of poor man's multiset. 221 template wrap_class_instances(T) { 222 int[T] wrap_class_instances; 223 } 224 225 /** 226 * A useful check for whether a given class has been wrapped. Mainly used by 227 * the conversion functions (see make_object.d), but possibly useful elsewhere. 228 */ 229 template is_wrapped(T) { 230 bool is_wrapped = false; 231 } 232 233 // The list of wrapped methods for this class. 234 template wrapped_method_list(T) { 235 static PyMethodDef[] wrapped_method_list = [ 236 { null, null, 0, null } 237 ]; 238 } 239 240 // The list of wrapped properties for this class. 241 template wrapped_prop_list(T) { 242 static PyGetSetDef[] wrapped_prop_list = [ 243 { null, null, null, null, null } 244 ]; 245 } 239 ////////////////////////////// 240 // CLASS WRAPPING INTERFACE // 241 ////////////////////////////// 246 242 247 243 /** … … 321 317 * the same number of arguments. 322 318 */ 323 static void init(C 1=int, C2=int, C3=int, C4=int, C5=int, C6=int, C7=int, C8=int, C9=int, C10=int) () {319 static void init(C ...) () { 324 320 wrapped_class_type!(T).tp_init = 325 &wrapped_ctors!(T, Tuple!(C1, C2, C3, C4, C5, C6, C7, C8, C9, C10)).init_func;321 &wrapped_ctors!(T, C).init_func; 326 322 } 327 323 … … 367 363 368 364 assert(DPy_Module_p !is null, "Must initialize module before wrapping classes."); 369 char[] module_name = .toString(PyModule_GetName(DPy_Module_p)); 370 365 char[] module_name = toString(PyModule_GetName(DPy_Module_p)); 371 366 // Fill in missing values 372 type.ob_type = PyType_Type_p; 367 type.ob_type = PyType_Type_p(); 368 //type.tp_new = &(wrapped_methods!(T).wrapped_new); 369 //type.tp_dealloc = &(wrapped_methods!(T).wrapped_dealloc); 373 370 type.tp_basicsize = (wrapped_class_object!(T)).sizeof; 374 371 type.tp_doc = name ~ " objects" ~ \0; 372 type.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE; 375 373 //type.tp_new = &PyType_GenericNew; 376 type.tp_repr = &wrapped_repr!(T).repr;374 //type.tp_repr = &wrapped_repr!(T).repr; 377 375 type.tp_methods = wrapped_method_list!(T); 378 376 type.tp_name = module_name ~ "." ~ name ~ \0; … … 409 407 410 408 // If a ctor wasn't supplied, try the default. 411 if (type.tp_init is null) {412 type.tp_init = &wrapped_init!(T).init;413 }409 //if (type.tp_init is null) { 410 // type.tp_init = &wrapped_init!(T).init; 411 //} 414 412 if (PyType_Ready(&type) < 0) { 415 413 // XXX: This will probably crash the interpreter, as it isn't normally … … 422 420 wrapped_classes[typeid(T)] = true; 423 421 } 422 423 /////////////////////// 424 // PYD API FUNCTIONS // 425 /////////////////////// 424 426 425 427 /** … … 442 444 } 443 445 446 /** 447 * Returns the object contained in a Python wrapped type. 448 */ 444 449 T WrapPyObject_AsObject(T) (PyObject* _self) { 445 450 alias wrapped_class_object!(T) wrapped_object; … … 469 474 if (t !is null) wrap_class_instances!(T)[t]++; 470 475 } 476 trunk/infrastructure/pyd/ctor_wrap.d
r40 r45 28 28 private import pyd.make_object; 29 29 30 private import meta.Tuple; 31 private import meta.Bind; 32 private import meta.Instantiate; 30 private import std.traits; 33 31 34 template ctor_redirect(T) { 35 T call_ctor()() { 36 return new T(); 37 } 38 39 T call_ctor(T1)(T1 t1) { 40 return new T(t1); 41 } 42 43 T call_ctor(T1, T2)(T1 t1, T2 t2) { 44 return new T(t1, t2); 45 } 46 47 T call_ctor(T1, T2, T3)(T1 t1, T2 t2, T3 t3) { 48 return new T(t1, t2, t3); 49 } 50 51 T call_ctor(T1, T2, T3, T4)(T1 t1, T2 t2, T3 t3, T4 t4) { 52 return new T(t1, t2, t3, t4); 53 } 54 55 T call_ctor(T1, T2, T3, T4, T5)(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5) { 56 return new T(t1, t2, t3, t4, t5); 57 } 58 59 T call_ctor(T1, T2, T3, T4, T5, T6)(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6) { 60 return new T(t1, t2, t3, t4, t5, t6); 61 } 62 63 T call_ctor(T1, T2, T3, T4, T5, T6, T7)(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7) { 64 return new T(t1, t2, t3, t4, t5, t6, t7); 65 } 66 67 T call_ctor(T1, T2, T3, T4, T5, T6, T7, T8)(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8) { 68 return new T(t1, t2, t3, t4, t5, t6, t7, t8); 69 } 70 71 T call_ctor(T1, T2, T3, T4, T5, T6, T7, T8, T9)(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9) { 72 return new T(t1, t2, t3, t4, t5, t6, t7, t8, t9); 73 } 74 75 T call_ctor(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10)(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10) { 76 return new T(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10); 32 T call_ctor(T, Tu ...)(Tu t) { 33 return new T(t); 34 } 35 36 // The default __init__ method calls the class's zero-argument constructor. 37 template wrapped_init(T) { 38 alias wrapped_class_object!(T) wrap_object; 39 extern(C) 40 int init(PyObject* self, PyObject* args, PyObject* kwds) { 41 return exception_catcher({ 42 WrapPyObject_SetObj(self, new T); 43 return 0; 44 }); 77 45 } 78 46 } … … 81 49 // Tuples, which each describe a ctor of T, and uses them to wrap a Python 82 50 // tp_init function. 83 template wrapped_ctors(T, Tu) {51 template wrapped_ctors(T, C ...) { 84 52 alias wrapped_class_object!(T) wrap_object; 85 86 // The user can provide ctor footprints as either function pointer types87 // or as tuples. This converts either to a tuple.88 template ctorAsTuple(T) {89 static if (isTuple!(T))90 alias T ctorAsTuple;91 else static if (is(typeof(*T) == function))92 alias getFuncTuple!(T) ctorAsTuple;93 }94 95 // This loops through the passed Tuple type and extracts the actual ctor96 // types.97 template loop(uint current, NewTu = EmptyTuple) {98 static if (current == Tu.length || is(typeof(Tu.mix.val!(current))==int)) {99 alias NewTu type;100 } else {101 alias loop!(current+1, NewTu.mix.appendT!(ctorAsTuple!(typeof(Tu.mix.val!(current))))).type type;102 }103 }104 alias loop!(0).type Ctors;105 106 // Checks each element of the Ctors tuple against the number of arguments107 // passed in from Python. Then, it calls the ctor with the passed-in108 // arguments.109 int findAndCallCtor(uint current) (PyObject* self, PyObject* args, int argCount) {110 static if (current == Ctors.length) {111 // No match, handle error112 PyErr_SetString(PyExc_TypeError, "Unsupported number of constructor arguments.");113 return -1;114 } else {115 alias typeof(Ctors.mix.val!(current)) Ctor;116 if (Ctor.length == argCount) {117 alias instantiateTemplate!(ctor_redirect!(T).call_ctor, Ctor) fn;118 WrapPyObject_SetObj(self, py_call(&fn, args));119 return 0;120 } else {121 return findAndCallCtor!(current+1)(self, args, argCount);122 }123 }124 }125 53 126 54 extern(C) … … 136 64 } 137 65 } 138 return findAndCallCtor!(0) (self, args, len); 66 // find another Ctor 67 C c; 68 foreach(i, arg; c) { 69 alias ParameterTypeTuple!(typeof(arg)) Ctor; 70 if (Ctor.length == len) { 71 alias call_ctor!(T, ParameterTypeTuple!(typeof(arg))) fn; 72 WrapPyObject_SetObj(self, py_call(&fn, args)); 73 return 0; 74 } 75 } 76 // No ctor found 77 PyErr_SetString(PyExc_TypeError, "Unsupported number of constructor arguments."); 78 return -1; 139 79 }); 140 80 } trunk/infrastructure/pyd/def.d
r40 r45 24 24 private import python; 25 25 26 private import pyd.class_wrap;27 private import pyd.dg_convert;28 private import pyd.exception;29 26 private import pyd.func_wrap; 30 private import pyd.make_object;31 27 32 28 private import meta.Default; 33 29 private import meta.Nameof; 34 35 private import std.string;36 30 37 31 private trunk/infrastructure/pyd/dg_convert.d
