Thread overview | |||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
June 13, 2006 Wrapping Python - A function wrapping template | ||||
---|---|---|---|---|
| ||||
In wrapping Python with D, I have just made a large step: [testdll.d] import python; import pyd.pyd; // My "Python/D" package int str_len(char[] str) { return str.length; } extern (C) { PyMethodDef testdll_GlobalMethods[] = [ { "str_len", cast(PyCFunction)&func_wrap!(str_len).func, METH_VARARGS, "" }, { null, null, 0, null } ]; export void inittestdll() { _loadPythonSupport(); PyObject* m = Py_InitModule("testdll", testdll_GlobalMethods); } } /* end extern (C) */ // EOF (In a Python session:) >>> import testdll >>> testdll.str_len("This") 4 Note the "func_wrap" template. This takes a regular D function and wraps it with something that can be exposed to Python. There are some limitations, as yet: The arguments and return type of the function must be ones it knows how to convert to and from Python, and there is not yet a mechanism for adding types to this list. It also does not yet support default arguments. It would also be nice to wrap all of the business with the method definition array. This can all be done. I'd like to acknowledge the work of David Rushby, whose "celerid" project and updated Python header were invaluable, as well as Deja Augustine, who first took a crack at the header. Daniel Keep and Tom S also proivded some useful function property-deriving templates. This library, as it exists now, is more a proof-of-concept than a useful library, so I'm not quite prepared to release it yet. -Kirk McDonald |
June 13, 2006 Re: Wrapping Python - A function wrapping template | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kirk McDonald | Kirk McDonald wrote: > In wrapping Python with D, I have just made a large step: > > [testdll.d] > import python; > import pyd.pyd; // My "Python/D" package > > int str_len(char[] str) { > return str.length; > } > > extern (C) { > > PyMethodDef testdll_GlobalMethods[] = [ > { "str_len", cast(PyCFunction)&func_wrap!(str_len).func, > METH_VARARGS, "" }, > { null, null, 0, null } > ]; > > export void inittestdll() { > _loadPythonSupport(); > > PyObject* m = Py_InitModule("testdll", testdll_GlobalMethods); > } > > } /* end extern (C) */ > // EOF > > (In a Python session:) >>>> import testdll >>>> testdll.str_len("This") > 4 > > Note the "func_wrap" template. This takes a regular D function and wraps it with something that can be exposed to Python. There are some limitations, as yet: The arguments and return type of the function must be ones it knows how to convert to and from Python, and there is not yet a mechanism for adding types to this list. It also does not yet support default arguments. It would also be nice to wrap all of the business with the method definition array. This can all be done. > > I'd like to acknowledge the work of David Rushby, whose "celerid" project and updated Python header were invaluable, as well as Deja Augustine, who first took a crack at the header. > > Daniel Keep and Tom S also proivded some useful function property-deriving templates. > > This library, as it exists now, is more a proof-of-concept than a useful library, so I'm not quite prepared to release it yet. > > -Kirk McDonald You stole my idea :P Seriously, congratulations. I know I didn't quite get that far. This is fantastic stuff; it won't be long now before we have our own version of Boost::Python :) Just a few questions: * How did you deal with the whole 8-bit with encodings <==> UTF-8 thing? I was seriously considering just forcing everything to go via UTF-16, or did you write code to do the transcoding manually? * Do you have any plans on how to wrap the method definition array? I tried using nested templates but D didn't like it :( In any case, fantastic work. -- Daniel -- Unlike Knuth, I have neither proven or tried the above; it may not even make sense. v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/ |
June 13, 2006 Re: Wrapping Python - A function wrapping template | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kirk McDonald | Kirk McDonald wrote: > This library, as it exists now, is more a proof-of-concept than a useful library, so I'm not quite prepared to release it yet. Looks sweet ! :) Hmmm... considering the code: { "str_len", cast(PyCFunction)&func_wrap!(str_len).func, METH_VARARGS, "" }, what's the purpose of 'cast(PyCFunction)&func_wrap!(str_len).func' ? couldn't it be replaced by just a single 'pycFunction!(str_len)' or something like this ? Keep up the great work ! -- Tomasz Stachowiak /+ a.k.a. h3r3tic +/ |
June 13, 2006 Re: Wrapping Python - A function wrapping template | ||||
---|---|---|---|---|
| ||||
Posted in reply to Daniel Keep | Daniel Keep wrote: > Kirk McDonald wrote: >>This library, as it exists now, is more a proof-of-concept than a useful >>library, so I'm not quite prepared to release it yet. >> > > > You stole my idea :P > > Seriously, congratulations. I know I didn't quite get that far. This > is fantastic stuff; it won't be long now before we have our own version > of Boost::Python :) > > Just a few questions: > > * How did you deal with the whole 8-bit with encodings <==> UTF-8 thing? > I was seriously considering just forcing everything to go via UTF-16, > or did you write code to do the transcoding manually? > I haven't. :-) That remains to be done. It just does ASCII at the moment. > * Do you have any plans on how to wrap the method definition array? I > tried using nested templates but D didn't like it :( My current instinct is to hide the array in the library, and add a "def" function (a la Boost::Python) that knows how to add entries to it. Haven't tried this yet, of course. > > In any case, fantastic work. Thanks! -Kirk McDonald |
June 13, 2006 Re: Wrapping Python - A function wrapping template | ||||
---|---|---|---|---|
| ||||
Posted in reply to Tom S | Tom S wrote: > Kirk McDonald wrote: > >> This library, as it exists now, is more a proof-of-concept than a useful library, so I'm not quite prepared to release it yet. > > > Looks sweet ! :) > > > Hmmm... considering the code: > > { "str_len", cast(PyCFunction)&func_wrap!(str_len).func, METH_VARARGS, "" }, > > what's the purpose of 'cast(PyCFunction)&func_wrap!(str_len).func' ? couldn't it be replaced by just a single 'pycFunction!(str_len)' or something like this ? > > All of that will eventually be wrapped. I could indeed tighten up the interface easily enough, and I have some other ideas of how to do that. > Keep up the great work ! > > Thanks! -Kirk McDonald |
June 13, 2006 Re: Wrapping Python - A function wrapping template | ||||
---|---|---|---|---|
| ||||
Posted in reply to Daniel Keep | Daniel Keep wrote: > * Do you have any plans on how to wrap the method definition array? I > tried using nested templates but D didn't like it :( May I know which part of nested templates it didn't like ? -- Tomasz Stachowiak /+ a.k.a. h3r3tic +/ |
June 13, 2006 Re: Wrapping Python - A function wrapping template | ||||
---|---|---|---|---|
| ||||
Posted in reply to Tom S | Tom S wrote: > Daniel Keep wrote: >> * Do you have any plans on how to wrap the method definition array? I tried using nested templates but D didn't like it :( > > May I know which part of nested templates it didn't like ? > I deleted the code a while back, but it was basically using these nested, recursive templates so that I could do this: alias StartModule!("Quxx").AddMethod!("foo", PydWrap!(foo)).AddMethod!("bar", PydWrap!(bar)).EndModule!() QuxxModule; However, D complained of various things. Funny thing was, THIS worked: alias StartModule!("Quxx") t1; alias t1.AddMethod!("foo", PydWrap!(foo)) t2; alias t2.AddMethod!("bar", PydWrap!(bar)) t3; alias t3.EndModule!() QuxxModule; But I figured that was as much, if not more verbose then doing it "long-hand", so I gave up. -- Daniel P.S. Like so many things, I can't actually remember specifics of how I defined that thing, but that was the gist of it. -- Unlike Knuth, I have neither proven or tried the above; it may not even make sense. v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/ |
June 13, 2006 Re: Wrapping Python - A function wrapping template | ||||
---|---|---|---|---|
| ||||
Posted in reply to Daniel Keep | Daniel Keep wrote: > I deleted the code a while back, but it was basically using these > nested, recursive templates so that I could do this: > > alias StartModule!("Quxx").AddMethod!("foo", > PydWrap!(foo)).AddMethod!("bar", PydWrap!(bar)).EndModule!() QuxxModule; > > However, D complained of various things. Funny thing was, THIS worked: > > alias StartModule!("Quxx") t1; > alias t1.AddMethod!("foo", PydWrap!(foo)) t2; > alias t2.AddMethod!("bar", PydWrap!(bar)) t3; > alias t3.EndModule!() QuxxModule; > > But I figured that was as much, if not more verbose then doing it > "long-hand", so I gave up. Could this: http://158.75.59.9/~h3/tmp/tmp4.d possibly help in any way ? -- Tomasz Stachowiak /+ a.k.a. h3r3tic +/ |
June 14, 2006 Re: Wrapping Python - A function wrapping template | ||||
---|---|---|---|---|
| ||||
Posted in reply to Tom S | Tom S wrote: > Daniel Keep wrote: >> I deleted the code a while back, but it was basically using these nested, recursive templates so that I could do this: >> >> alias StartModule!("Quxx").AddMethod!("foo", >> PydWrap!(foo)).AddMethod!("bar", PydWrap!(bar)).EndModule!() QuxxModule; >> >> However, D complained of various things. Funny thing was, THIS worked: >> >> alias StartModule!("Quxx") t1; >> alias t1.AddMethod!("foo", PydWrap!(foo)) t2; >> alias t2.AddMethod!("bar", PydWrap!(bar)) t3; >> alias t3.EndModule!() QuxxModule; >> >> But I figured that was as much, if not more verbose then doing it "long-hand", so I gave up. > > > Could this: http://158.75.59.9/~h3/tmp/tmp4.d possibly help in any way ? > It just might :) Thanks for that. -- Daniel -- Unlike Knuth, I have neither proven or tried the above; it may not even make sense. v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/ |
June 15, 2006 Re: Wrapping Python - A function wrapping template | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kirk McDonald | Kirk McDonald wrote:
> In wrapping Python with D, I have just made a large step:
>
I've just done two things with regard to this wrapper:
First, I've implemented some basic exception wrapping. If a wrapped Python API function raises a Python exception, this is now captured and thrown as a D exception. If this exception is not caught by user code, it is caught by the function wrapping template, and translated back into the original Python exception. If a D exception is thrown and not caught by user code, the function wrapping template will translate it into a Python RuntimeError and pass along the message.
On the "to do" list is creating a hierarchy of D exception classes that mirrors the hierarchy of Python exceptions, as at the moment there is a single "PythonException" class. It might also be nice to provide some Python exceptions that mirror various D exceptions, for when those escape into the interpreter. (Alternately, one might map them onto an appropriate existing Python exception.)
Second, the function wrapper now supports void return types. Imagine my suprise when I realised it didn't support them before! (It was sort of a "duh" moment.) Adding this support roughly doubled the length of the template, which wasn't short to begin with. Each number of arguments the wrapped function can accept (from 0 to 10) has its own "static if" clause, and now each of these has been doubled, as functions with return types to capture must be called differently than those without. Anyway, functions with a void return type now return Py_None as per the usual Python idiom.
-Kirk McDonald
|
Copyright © 1999-2021 by the D Language Foundation