You can subscribe to this list here.
2001 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
(8) |
Sep
(5) |
Oct
(1) |
Nov
|
Dec
|
---|---|---|---|---|---|---|---|---|---|---|---|---|
2002 |
Jan
|
Feb
|
Mar
(1) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: Mitchell N C. <mch...@ve...> - 2002-03-11 04:11:57
|
This note recently went out to python-list. Fyi, Mitchell ----[]---- Date: Sat, 9 Mar 2002 14:44:02 -0500 To: pyt...@py... Subject: An Optimization Anecdote about PyInline From: Mitchell N Charity <mch...@ve...> Guido's "Python Patterns - An Optimization Anecdote" (http://www.python.org/doc/essays/list2str.html) explores the performance of various ways of converting a list of integers into a string of characters. Such as the straightforward def f1(list): string = "" for item in list: string = string + chr(item) return string and the fastest version import array def f7(list): return array.array('B', list).tostring() # Use 'B' with Python2.2, 'b' with Python1.5 Guido writes [...] I had wanted to try one more approach: write the whole function in C. [...] Given the effort of writing and testing an extension (compared to whipping up those Python one-liners), as well as the dependency on a non-standard Python extension, I decided not to pursue this option... I wanted to revisit this, because with PyInline, the effort has diminished, and a non-standard extension is not required (just PyInline). And, as Guido points out, If you feel the need for speed, [...] - you can't beat a loop written in C. So, here then is a new version, f8(), which uses PyInline. from PyInline import C import __main__ C.Builder(code=""" PyObject* f8(PyObject *list) { PyObject* string = NULL; unsigned char* buffer = NULL; int size, index; #define RAISE(errtype,msg) { PyErr_SetString(errtype,msg); RE_RAISE; } #define RE_RAISE { Py_XDECREF(string); return NULL; } if(!PyList_Check(list)) RAISE(PyExc_TypeError,"a list is required"); size = PyList_Size(list); if(size < 0) RE_RAISE; string = PyString_FromStringAndSize(NULL, size); if(string == NULL) RE_RAISE; buffer = PyString_AsString(string); if(buffer == NULL) RE_RAISE; for(index = 0; index < size; index++) { PyObject *item = NULL; long number; item = PyList_GetItem(list,index); if(item == NULL) RE_RAISE; number = PyInt_AsLong(item); if(PyErr_Occurred() != NULL) RE_RAISE; if(number < 0 || number > 255) RAISE(PyExc_TypeError,"an integer was out of range"); buffer[index] = (unsigned char) number; } return string; } """,targetmodule=__main__).build() The test jig requires a slight change #for f in testfuncs: print f.func_name, f(testdata) for f in testfuncs: print f(testdata) because PyInline currently generates glue which does not understand f.func_name. So, what is the result? First, the downsides. f8() is a C extension, and so only works with C-based Pythons. PyInline invokes an external C compiler, and cruftily caches the result in the filesystem. And, as PyInline is alpha code, there are little misfeatures like not being able to use func_name. Oh yes, and being written in C, f8() is perhaps two orders of magnitude more complex than the Python versions. Though, this last is perhaps a worst case, as f8() is almost all interface code, with maybe just three lines of algorithm. In more typical use, one might see a one order of magnitude cost. And with objects which provide a nice C api, maybe even less. The upside is f8() runs 5 times faster than f7(), the best alternative. And uses half the memory. That's 50 times faster than the naive versions. And again, when python interface code is less dominant, the speedup can be dramatically larger. So, restoring the phrase I clipped out of the quote above, "If you feel the need for speed, go for built-in functions - you can't beat a loop written in C.". And if there isn't one already, you might consider creating one with PyInline. Mitchell Charity (I'm working on a web page http://www.vendian.org/mncharity/dir3/inline/ which explores using PyInline, and Perl's Inline, with objects which provide C api's.) ----[]---- |
From: Ken S. <ksi...@tt...> - 2001-10-02 21:49:09
|
PyInline 0.03 ------------- The PyInline module allows you to put source code from other programming languages directly "inline" in a Python script or module. The code is automatically compiled as needed, and then loaded for immediate access from Python. PyInline is the Python equivalent of Brian Ingerson's Inline module for Perl (http://inline.perl.org). What's New in 0.03? ------------------- PyInline 0.03 provides Python 2.0 compatibility, an improved and simplified API, better parsing, and a much improved foundation for adding support for languages other than C. The new syntax is much cleaner: import PyInline m = PyInline.build(code=r""" #include <stdio.h> void ja(char *str) { printf("Just another %s hacker\n", str); } """, language="C") m.ja("Inline") Availability ------------ PyInline is maintained on SourceForge at http://sourceforge.net/projects/pyinline TTUL Ken -- Connect wirelessly at your favourite cafe with FatPort Network. http://www.FatPort.com -- Secure, Accountable Wireless |
From: Thomas H. <tho...@io...> - 2001-09-27 11:14:03
|
No comments? ----- Original Message ----- From: "Thomas Heller" <tho...@io...> To: "Ken Simpson" <ksi...@tt...>; <pyi...@li...> Sent: Friday, September 07, 2001 8:57 AM Subject: Re: [Pyinline-discuss] PyInline direction > > > 1. It wold be cool if the generated C-code would contain > > > #line directives pointing into the correct location > > > into the python source file, but I doubt that it is > > > possible to do it automatically. > > > > Great idea. It will take some work to implement, though, so let's write it > > down for implementation during the next month or so. > > The idea I have so far is to insert the C code in a function in this > way: > > C(""" > int foo(void) > { > return do_something(); > } > """) > > and the C function could be something like > > def C(code): > import sys > lineno = sys._getframe(1).f_lineno > return "#line %d\n" % lineno + code > > This way is not bullet-proof: > > print C("spam") > > works correctly, > > print C( > "spam") > > does not. > > > > > 2. Currently you automatically wrap C-functions > > > by parsing their header. This is (nearly) trivial > > > for simple argument and return types, but impossible > > > for structured types. How will this be handled? > > > > I'm planning to implement a Python equivalent of Neil Watkiss' > > Inline::Struct module for Perl. Inline::Struct lets you define C structs > > which are automagically turned into Perl dictionaries when they pass into > > Perl land (and vice versa). > Another great way would be to use Jack Jansen's bgen. > This is a module for generating the complete source code for > Python extension modules. Seems to be used quite extensively > for MacPython, although it is not Mac specific. > > You write manual functions in the following way: > > bgen.ManualGenerator("function_name", """ > if (!PyArg_ParseTuple(.....) > return NULL; > .... > return _res; > """) > > The function header is created automatically. > Or, better yet, create a Python interface function wrapping a C function like > int fib(int i) > in this way: > > c_int = bgen.Type("int", "i") > bgen.FunctionGenerator(c_int, "fib", (c_int, "n", InMode)) > > which will automatically create the following source: > > PyObject *spam_fib(PyObject *self, PyObject *args) > { > int n; > if (!PyArg_ParseTuple(args, "i", &n)) > return NULL; > return Py_BuildValue("i", fib(n)); > } > > Best is, bgen allows to easily create new Python types > in the extension module! > Looks much easier than SWIG! > The only problem so far is that there are no docs... > > ---- > > All in all, I have a lot of ideas, but different from you > I know nothing about Perls inline module. > > Big question is: Should we cooperate (open source development), > or do we split our efforts? > > Thomas > > > _______________________________________________ > Pyinline-discuss mailing list > Pyi...@li... > https://lists.sourceforge.net/lists/listinfo/pyinline-discuss |
From: Ken S. <ksi...@tt...> - 2001-09-27 00:48:50
|
PyInline 0.03 ------------- The PyInline module allows you to put source code from other programming languages directly "inline" in a Python script or module. The code is automatically compiled as needed, and then loaded for immediate access from Python. PyInline is the Python equivalent of Brian Ingerson's Inline module for Perl (http://inline.perl.org). What's New in 0.03? ------------------- PyInline 0.03 provides Python 2.0 compatibility, an improved and simplified API, better parsing, and a much improved foundation for adding support for languages other than C. The new syntax is much cleaner: import PyInline m = PyInline.build(code=r""" #include <stdio.h> void ja(char *str) { printf("Just another %s hacker\n", str); } """, language="C") m.ja("Inline") Availability ------------ PyInline is maintained on SourceForge at http://sourceforge.net/projects/pyinline TTUL Ken -- Connect wirelessly at your favourite cafe with FatPort Network. http://www.FatPort.com -- Fast, Easy, Convenient Wireless |
From: Thomas H. <tho...@io...> - 2001-09-07 07:11:16
|
> > 1. It wold be cool if the generated C-code would contain > > #line directives pointing into the correct location > > into the python source file, but I doubt that it is > > possible to do it automatically. > > Great idea. It will take some work to implement, though, so let's write it > down for implementation during the next month or so. The idea I have so far is to insert the C code in a function in this way: C(""" int foo(void) { return do_something(); } """) and the C function could be something like def C(code): import sys lineno = sys._getframe(1).f_lineno return "#line %d\n" % lineno + code This way is not bullet-proof: print C("spam") works correctly, print C( "spam") does not. > > > 2. Currently you automatically wrap C-functions > > by parsing their header. This is (nearly) trivial > > for simple argument and return types, but impossible > > for structured types. How will this be handled? > > I'm planning to implement a Python equivalent of Neil Watkiss' > Inline::Struct module for Perl. Inline::Struct lets you define C structs > which are automagically turned into Perl dictionaries when they pass into > Perl land (and vice versa). Another great way would be to use Jack Jansen's bgen. This is a module for generating the complete source code for Python extension modules. Seems to be used quite extensively for MacPython, although it is not Mac specific. You write manual functions in the following way: bgen.ManualGenerator("function_name", """ if (!PyArg_ParseTuple(.....) return NULL; .... return _res; """) The function header is created automatically. Or, better yet, create a Python interface function wrapping a C function like int fib(int i) in this way: c_int = bgen.Type("int", "i") bgen.FunctionGenerator(c_int, "fib", (c_int, "n", InMode)) which will automatically create the following source: PyObject *spam_fib(PyObject *self, PyObject *args) { int n; if (!PyArg_ParseTuple(args, "i", &n)) return NULL; return Py_BuildValue("i", fib(n)); } Best is, bgen allows to easily create new Python types in the extension module! Looks much easier than SWIG! The only problem so far is that there are no docs... ---- All in all, I have a lot of ideas, but different from you I know nothing about Perls inline module. Big question is: Should we cooperate (open source development), or do we split our efforts? Thomas |
From: Ken S. <ksi...@tt...> - 2001-09-06 21:48:33
|
> 1. It wold be cool if the generated C-code would contain > #line directives pointing into the correct location > into the python source file, but I doubt that it is > possible to do it automatically. Great idea. It will take some work to implement, though, so let's write it down for implementation during the next month or so. > 2. Currently you automatically wrap C-functions > by parsing their header. This is (nearly) trivial > for simple argument and return types, but impossible > for structured types. How will this be handled? I'm planning to implement a Python equivalent of Neil Watkiss' Inline::Struct module for Perl. Inline::Struct lets you define C structs which are automagically turned into Perl dictionaries when they pass into Perl land (and vice versa). > 3. Currently you import names in the module into > the current namespace. Wouldn't it be cool to write > > ... > PyInline.function(r""" > void ja(char *str) { > printf("Just another %s hacker\n", str); > } > """)("PyInline") Good idea. That ought not to be very difficult to implement (i.e., a few extra lines in PyInline/__init__.py). > or even > > class X: > meth = PyInline.method(r""" > void ja(PyObject *self, char *str) { > printf("Just another %s hacker\n", str); > }""") > > to define an instance method written in C? Great idea. TTUL Ken |
From: Jeff Y. <me...@je...> - 2001-09-01 01:19:54
|
On Fri, Aug 31, 2001 at 02:15:12PM -0700, Ken Simpson wrote: > Jeff Youel posted some interesting questions in his recent Ethernet MAC > address script (the first publicly announced script to use PyInline! -- > see it at http://www.jeffyouel.com), which I have paraphrased in this > email. Perhaps other PyInliners out there could help me find answers to > Jeff's questions. Thanks Ken. I updated it with your suggestions for exceptions and returning a PyObject. The latest is at http://www.jeffyouel.com/weblog/mac.py. ...snip... > 3. How can I ship my inline Python script along with its compiled > binary extensions? > > Currently, the only way to ship the binary part of your inline script is > to first run the script on your system to generate and compile any inlined > C source code and then ship the _PyInline_abc34234... directory along with > your script. > > I am currently discussing this problem with Brian Ingerson (of Inline for > Perl fame) and hope to have a better solution soon. Probably the new > solution will involve configuration files... > I was thinking about deploying scripts with inlined code on a Windows box (without a compiler). This would be very handy but not a rush for me. > 4. How do I keep from collecting dozens of _PyInline_* directories while > I'm developing? > > Currently, "rm -r _PyInline*" is the most effective strategy to reduce > clutter. In future, PyInline will provide a configuration file inside a > much better-named directory (perhaps _PyInline_MyModuleName) which > contains the MD5 checksum of all inlined sources so that PyInline knows > when to do a rebuild. Yeah, figured that. It's really just a minor issue. // Jeff |
From: Paul P. <pa...@Ac...> - 2001-08-31 22:33:17
|
Ken Simpson wrote: > >... > > 1. How do I raise Python exceptions from PyInline'd C code? What if the wrapper code *always* checked for PyErr_Occurred(). If it is set, it decref's the return value (if it isn't NULL) and then merely re-raises the exception. -- Take a recipe. Leave a recipe. Python Cookbook! http://www.ActiveState.com/pythoncookbook |
From: Ken S. <ksi...@tt...> - 2001-08-31 21:15:17
|
Jeff Youel posted some interesting questions in his recent Ethernet MAC address script (the first publicly announced script to use PyInline! -- see it at http://www.jeffyouel.com), which I have paraphrased in this email. Perhaps other PyInliners out there could help me find answers to Jeff's questions. 1. How do I raise Python exceptions from PyInline'd C code? To generate exceptions from your inlined Python functions, you must do some of the inlining legwork yourself. Rather than returning one of the standard C data types from your function, you must return a PyObject* and set up the return value using Py_BuildValue() or one of the other value-building functions in the Python C API. When you want to throw an exception, just call PyErr_SetString() or one of the other exception "throwing" functions and return NULL. For example, the following bit of Python defines a C function that adds two numbers together and returns the result, but which fires an exception if the result is zero. import PyInline m = PyInline.build(code=r""" PyObject* add(int a, int b) { PyObject* retval; int sum = a + b; if(sum == 0) { PyErr_SetString(PyExc_ValueError, "Sum must not be zero!"); return NULL; } else { retval = Py_BuildValue("i", sum); return retval; } } """, language="C") print m.add(10, 5) # Okay print m.add(10, -10) # Throws an exception. 2. How do I return dynamically allocated strings without leaking memory? Probably the easiest way to return a dynamically allocated string is to just return a PyObject* from your PyInlined function. For example, import PyInline m = PyInline.build(code=r""" PyObject* genstring(void) { PyObject* retval = Py_BuildValue("s", "This is my special string."); return retval; } """, language="C") str = m.genstring() print str PyInline knows that if you return a PyObject* from your inlined C function, the PyObject* should just be passed verbatim back to Python. 3. How can I ship my inline Python script along with its compiled binary extensions? Currently, the only way to ship the binary part of your inline script is to first run the script on your system to generate and compile any inlined C source code and then ship the _PyInline_abc34234... directory along with your script. I am currently discussing this problem with Brian Ingerson (of Inline for Perl fame) and hope to have a better solution soon. Probably the new solution will involve configuration files... 4. How do I keep from collecting dozens of _PyInline_* directories while I'm developing? Currently, "rm -r _PyInline*" is the most effective strategy to reduce clutter. In future, PyInline will provide a configuration file inside a much better-named directory (perhaps _PyInline_MyModuleName) which contains the MD5 checksum of all inlined sources so that PyInline knows when to do a rebuild. TTUL Ken On Fri, 31 Aug 2001, Ken Simpson wrote: > Hi Jeff, > I was wondering whether you would mind if I added your PyInline MAC > address script to the examples directory of PyInline? > > To my knowledge, your script is the first real-world use of PyInline! > > TTUL > Ken > > |
From: Thomas H. <tho...@io...> - 2001-08-30 17:14:44
|
Ken, I would like to hear more of the direction PyInline is heading at, I also have some ideas. 1. It wold be cool if the generated C-code would contain #line directives pointing into the correct location into the python source file, but I doubt that it is possible to do it automatically. 2. Currently you automatically wrap C-functions by parsing their header. This is (nearly) trivial for simple argument and return types, but impossible for structured types. How will this be handled? 3. Currently you import names in the module into the current namespace. Wouldn't it be cool to write func = PyInline.function(r""" void ja(char *str) { printf("Just another %s hacker\n", str); } """) func("Inline") or even PyInline.function(r""" void ja(char *str) { printf("Just another %s hacker\n", str); } """)("PyInline") or even class X: meth = PyInline.method(r""" void ja(PyObject *self, char *str) { printf("Just another %s hacker\n", str); }""") to define an instance method written in C? Thomas |
From: Ken S. <ksi...@tt...> - 2001-08-29 23:07:56
|
Hi PyInliners, FYI, the latest and greatest PyInline is always available via CVS. To check PyInline out, use the following commands from your terminal: cvs -d:pserver:ano...@cv...:/cvsroot/pyinline login cvs -z3 -d:pserver:ano...@cv...:/cvsroot/pyinline \ co PyInline i.e., your CVSROOT should be set to :pserver:ano...@cv...:/cvsroot/pyinline Once you have checked PyInline out, you can use "cvs update" from the PyInline directory to make sure you always have the latest version. Also... Today I added a build() function to the PyInline module, which insulates you from some of the complexity of building a chunk of inlined code. build() creates a Builder object and then calls build() on that object to make your code. The biggest change with build() is that you now pass in not only your code chunk but also the language your code is written in. build() finds the right PyInline language module and handles setting up and building your code with that module. For example: import PyInline m = PyInline.build(code=r""" #include <stdio.h> void ja(char *str) { printf("Just another %s hacker\n", str); } """, language="C") # And this is written in C. m.ja("Inline") Comments and criticisms are always welcome :) TTUL Ken -- import PyInline PyInline.build(code=r'void ja(char* s){printf("Just another %s hacker\n",s);}',\ language='C').ja("Inline") |
From: Ken S. <ksi...@tt...> - 2001-08-29 18:34:54
|
> Inspired by the recent discussion of perls inline > module I wrote the attached module, which is yet > another way to do it. Thanks for posting your solution, Thomas. I have added another example (example4.py) which steals your Fibonacci function and demonstrates how you can add Inlined C methods to a Python class. I also just added (but have not yet committed into CVS) a build() method to the PyInline class, which simplifies and abstracts the build process. e.g., import PyInline, __main__ PyInline.build(code=r""" #include <stdio.h> void ja(char *str) { printf("Just another %s hacker\n", str); } """, targetmodule=__main__, language = 'C') ja("Inline") TTUL Ken > Thomas > > ----inline.py--- > class C_Func: > def __init__(self, inline, name, code, doc, prefix): > self.name = name > self.code = code > self.doc = doc > self.module = inline > self.prefix = prefix > > def create(self, file): > file.write("static PyObject *%s(PyObject *self, PyObject *args)\n"\ > % (self.prefix + self.name)) > file.write(self.code) > file.write("\n"); > > def __call__(self, *args, **kw): > mod = self.module.create() > func = getattr(mod, self.name) > return func(*args, **kw) > > class Inline: > def __init__(self, name): > self.name = name > self.functions = {} > self.mod = None > self.libraries = [] > > def c_func(self, name, code, doc=None, prefix=''): > if self.mod: > raise RuntimeError, \ > "Cannot add any more functions: Extension already created" > func = C_Func(self, name, code, doc, prefix) > self.functions[name] = func > return func > > def create(self): > if not self.mod: > # generate the code > import StringIO > buffer = StringIO.StringIO() > buffer.write("#include <python.h>\n") > buffer.write("\n") > > for func in self.functions.values(): > func.create(buffer) > > buffer.write("static PyMethodDef methods[] = {\n") > for fname in self.functions.keys(): > pre = self.functions[fname].prefix > buffer.write(' { "%s", %s, METH_VARARGS },\n' % \ > (fname, pre + fname)) > buffer.write(' { NULL }, /* sentinel */\n};\n') > buffer.write("\n") > > buffer.write('void init%s(void)\n' % self.name) > buffer.write('{\n Py_InitModule3("%s", methods, "");\n}\n' % \ > self.name) > > code = buffer.getvalue() > buffer.close() > > # calulate md5 digest > import md5 > m = md5.new() > m.update(code) > hd = m.hexdigest() > > # compare to existing digest, if present > try: > old_md5 = open(self.name + '.md5', 'r').read() > except: > old_md5 = None > > # if the digests match, no recompilation is needed > if old_md5 != hd: > # recompilation needed > file = open(self.name + '.c', 'w') > file.write(code) > file.close() > > from distutils.core import setup, Extension > > ext = Extension(self.name, sources=[self.name + '.c'], > libraries=self.libraries) > > setup(ext_modules=[ext], script_name="dummy", > script_args=["-q", "install", "--install-platlib=."]) > > open(self.name + '.md5', 'w').write(hd) > import os > os.remove(self.name + '.c') > > # import module > self.mod = __import__(self.name) > > def __getattr__(self, name): > if name not in self.functions.keys(): > raise AttributeError, name > if not self.mod: > self.create() > return getattr(self.mod, name) > > if __name__ == '__main__': > module = Inline("_sample") > > # define a function implemented in C > # The function declaration will be added automatically, > # in this case 'static PyObject *fib_c(PyObject *self, PyObject *args)' > module.c_func("fib_c", r""" > { > int i; > static int _fib(int); > if (!PyArg_ParseTuple(args, "i", &i)) > return NULL; > return Py_BuildValue("i", _fib(i)); > } > > static int _fib(int i) > { > if (i <= 2) > return i; > return _fib(i - 1) + _fib(i - 2); > } > """) > > > # define a function implemented in C > # The function declaration will be added automatically, > # in this case 'static PyObject *fib_c(PyObject *self, PyObject *args)' > module.c_func("fact_c", r""" > { > int i; > PyObject *inst; > static int _fact(int); > if (!PyArg_ParseTuple(args, "Oi", &inst, &i)) > return NULL; > return Py_BuildValue("i", _fact(i)); > } > > static int _fact(int i) > { > if (i <= 1) > return i; > return i * _fact(i - 1); > } > """) > > > > # generate and compile an extension module (if needed), > # retrieve the function from it. > fib_c = module.fib_c > > > # a similar function implemented in Python > def fib_py(i): > if i <= 2: > return i > return fib_py(i-1) + fib_py(i-2) > > # we can also define a class, and use the extension module's functions > # as instance methods > class X: > def fact_py(self, i): > if i <= 1: > return i > return i * self.fact_py(i-1) > > # convert the extension function into a unbound method > # and attach it to the class > import new > X.fact_c = new.instancemethod(module.fact_c, None, X) > > # do a little benchmark > import time > > start = time.clock() > print "fib_py(30) =", fib_py(30), "%s seconds" % (time.clock() - start) > > start = time.clock() > print "fib_c(30) =", fib_c(30), "%s seconds" % (time.clock() - start) > > x = X() > > start = time.clock() > print "x.fact_py(12) =", x.fact_py(12), "%s seconds" % (time.clock() - start) > > start = time.clock() > print "x.fact_c(12) =", x.fact_c(12), "%s seconds" % (time.clock() - start) > > > > > > > _______________________________________________ > Pyinline-discuss mailing list > Pyi...@li... > http://lists.sourceforge.net/lists/listinfo/pyinline-discuss > |
From: Ken S. <ksi...@tt...> - 2001-08-29 17:21:07
|
> Now it works like magic! Much a relief from the chore of making extensions. Excellent! Thanks for testing it on Windows! Let me know if you have any suggestions as to how PyInline could be improved or if you know of any other bugs. TTUL Ken > From: "Ken Simpson" <ksi...@tt...> > To: "Changjune Kim" <ju...@no...> > Sent: Thursday, August 30, 2001 1:50 AM > Subject: Re: PyInline Released: Put C source code directly "inline" with your > Python! > > > > Hi, > > You're actually the first person who has ever tried using PyInline on > > Windows -- congratulations! > > > > This patch should fix the problem: > > > > diff -d -u -r1.1 example1.py > > --- example1.py 2001/08/28 17:39:58 1.1 > > +++ example1.py 2001/08/29 16:47:32 > > @@ -3,7 +3,7 @@ > > > > # Test the simplest of C bindings. > > > > -x = C.Builder(code=""" > > +x = C.Builder(code=r""" > > #include <stdio.h> > > void ja(char *str) { > > printf("Just another %s hacker\n", str); > > > > > > > > TTUL > > Ken > > > > > > On Thu, 30 Aug 2001, Changjune Kim wrote: > > > > > Thank you for the wonderful module, but I'm having some problem running it > on > > > Win32. > > > > > > When I run example1.py, I get the following: > > > > > > _PyInline_2b20b1d415f9c78f6af9b890ff25a82a.c > > > _PyInline_2b20b1d415f9c78f6af9b890ff25a82a.c(10) : error C2001: newline in > > > constant > > > _PyInline_2b20b1d415f9c78f6af9b890ff25a82a.c(11) : error C2001: newline in > > > constant > > > _PyInline_2b20b1d415f9c78f6af9b890ff25a82a.c(12) : error C2143: syntax > error : > > > missing ')' before '}' > > > _PyInline_2b20b1d415f9c78f6af9b890ff25a82a.c(22) : error C2065: 'args' : > > > undeclared identifier > > > _PyInline_2b20b1d415f9c78f6af9b890ff25a82a.c(22) : warning C4047: > 'function' : > > > 'struct _object *' differs in levels of indirection from 'int ' > > > _PyInline_2b20b1d415f9c78f6af9b890ff25a82a.c(22) : warning C4024: > > > 'PyArg_ParseTuple' : different types for formal and actual parameter 1 > > > _PyInline_2b20b1d415f9c78f6af9b890ff25a82a.c(23) : warning C4098: 'ja' : > > > 'void' function returning a value > > > _PyInline_2b20b1d415f9c78f6af9b890ff25a82a.c(27) : warning C4098: 'ja' : > > > 'void' function returning a value > > > _PyInline_2b20b1d415f9c78f6af9b890ff25a82a.c(30) : error C2061: syntax > error : > > > identifier '_PyInline_2b20b1d415f9c78f6af9b890ff25a82a_Methods' > > > _PyInline_2b20b1d415f9c78f6af9b890ff25a82a.c(30) : error C2059: syntax > error : > > > ';' > > > _PyInline_2b20b1d415f9c78f6af9b890ff25a82a.c(30) : error C2059: syntax > error : > > > '[' > > > _PyInline_2b20b1d415f9c78f6af9b890ff25a82a.c(37) : error C2065: > > > '_PyInline_2b20b1d415f9c78f6af9b890ff25a82a_Methods' : undeclared > identifier > > > _PyInline_2b20b1d415f9c78f6af9b890ff25a82a.c(37) : warning C4047: > 'function' : > > > 'struct PyMethodDef *' differs in levels of indirection from 'int ' > > > _PyInline_2b20b1d415f9c78f6af9b890ff25a82a.c(37) : warning C4024: > > > 'Py_InitModule4' : different types for formal and actual parameter 2 > > > running build > > > running build_ext > > > building '_PyInline_2b20b1d415f9c78f6af9b890ff25a82a' extension > > > creating build > > > creating build\temp.win32-2.2 > > > creating build\temp.win32-2.2\Release > > > C:\Program Files\Microsoft Visual Studio\VC98\BIN\cl.exe /c /nologo /Ox > /MD > > > /W3 /GX -IC:\PYTHON22\Include > /Tc_PyInline_2b20b1d415f9c78f6af9b890ff25a82a.c > > > > /Fobuild\temp.win32-2.2\Release\_PyInline_2b20b1d415f9c78f6af9b890ff25a82a.obj > > > error: command '"C:\Program Files\Microsoft Visual > Studio\VC98\BIN\cl.exe"' > > > fail > > > ed with exit status 2 > > > > > > ----- Original Message ----- > > > From: "Ken Simpson" <ksi...@tt...> > > > Newsgroups: comp.lang.python > > > Sent: Wednesday, August 29, 2001 3:05 AM > > > Subject: PyInline Released: Put C source code directly "inline" with your > > > Python! > > > > > > > > > > The PyInline module allows you to put source code from other > > > > programming languages directly "inline" in a Python script or > > > > module. The code is automatically compiled as needed and then loaded > > > > for immediate access from Python. > > > > > > > > In short, PyInline lets you do things like this: > > > > > > > > from PyInline import C > > > > import __main__ > > > > > > > > # Let's put some C code "inline" with our Python: > > > > > > > > x = C.Builder(code=""" > > > > > > > > #include <stdio.h> > > > > void ja(char *str) { > > > > printf("Just another %s hacker\n", str); > > > > } > > > > > > > > """, targetmodule=__main__) # Add C methods to the __main__ module. > > > > > > > > x.build() > > > > ja("Inline") > > > > --- > > > > > > > > PyInline is the Python equivalent of > > > > Brian Ingerson's Inline module for Perl (http://inline.perl.org), > > > > which was awarded the "Best Module" award at this year's Perl > > > > Conference. > > > > > > > > More information about PyInline can be found at the PyInline home page > > > > on > > > > SourceForge: > > > > > > > > http://pyinline.sourceforge.net > > > > > > > > To discuss PyInline further, please join the pyinline-discuss mailing > > > > list at > > > > http://lists.sourceforge.net/lists/listinfo/pyinline-discuss > > > > |
From: Thomas H. <tho...@io...> - 2001-08-29 07:11:28
|
Inspired by the recent discussion of perls inline module I wrote the attached module, which is yet another way to do it. Enjoy, Thomas ----inline.py--- class C_Func: def __init__(self, inline, name, code, doc, prefix): self.name = name self.code = code self.doc = doc self.module = inline self.prefix = prefix def create(self, file): file.write("static PyObject *%s(PyObject *self, PyObject *args)\n"\ % (self.prefix + self.name)) file.write(self.code) file.write("\n"); def __call__(self, *args, **kw): mod = self.module.create() func = getattr(mod, self.name) return func(*args, **kw) class Inline: def __init__(self, name): self.name = name self.functions = {} self.mod = None self.libraries = [] def c_func(self, name, code, doc=None, prefix=''): if self.mod: raise RuntimeError, \ "Cannot add any more functions: Extension already created" func = C_Func(self, name, code, doc, prefix) self.functions[name] = func return func def create(self): if not self.mod: # generate the code import StringIO buffer = StringIO.StringIO() buffer.write("#include <python.h>\n") buffer.write("\n") for func in self.functions.values(): func.create(buffer) buffer.write("static PyMethodDef methods[] = {\n") for fname in self.functions.keys(): pre = self.functions[fname].prefix buffer.write(' { "%s", %s, METH_VARARGS },\n' % \ (fname, pre + fname)) buffer.write(' { NULL }, /* sentinel */\n};\n') buffer.write("\n") buffer.write('void init%s(void)\n' % self.name) buffer.write('{\n Py_InitModule3("%s", methods, "");\n}\n' % \ self.name) code = buffer.getvalue() buffer.close() # calulate md5 digest import md5 m = md5.new() m.update(code) hd = m.hexdigest() # compare to existing digest, if present try: old_md5 = open(self.name + '.md5', 'r').read() except: old_md5 = None # if the digests match, no recompilation is needed if old_md5 != hd: # recompilation needed file = open(self.name + '.c', 'w') file.write(code) file.close() from distutils.core import setup, Extension ext = Extension(self.name, sources=[self.name + '.c'], libraries=self.libraries) setup(ext_modules=[ext], script_name="dummy", script_args=["-q", "install", "--install-platlib=."]) open(self.name + '.md5', 'w').write(hd) import os os.remove(self.name + '.c') # import module self.mod = __import__(self.name) def __getattr__(self, name): if name not in self.functions.keys(): raise AttributeError, name if not self.mod: self.create() return getattr(self.mod, name) if __name__ == '__main__': module = Inline("_sample") # define a function implemented in C # The function declaration will be added automatically, # in this case 'static PyObject *fib_c(PyObject *self, PyObject *args)' module.c_func("fib_c", r""" { int i; static int _fib(int); if (!PyArg_ParseTuple(args, "i", &i)) return NULL; return Py_BuildValue("i", _fib(i)); } static int _fib(int i) { if (i <= 2) return i; return _fib(i - 1) + _fib(i - 2); } """) # define a function implemented in C # The function declaration will be added automatically, # in this case 'static PyObject *fib_c(PyObject *self, PyObject *args)' module.c_func("fact_c", r""" { int i; PyObject *inst; static int _fact(int); if (!PyArg_ParseTuple(args, "Oi", &inst, &i)) return NULL; return Py_BuildValue("i", _fact(i)); } static int _fact(int i) { if (i <= 1) return i; return i * _fact(i - 1); } """) # generate and compile an extension module (if needed), # retrieve the function from it. fib_c = module.fib_c # a similar function implemented in Python def fib_py(i): if i <= 2: return i return fib_py(i-1) + fib_py(i-2) # we can also define a class, and use the extension module's functions # as instance methods class X: def fact_py(self, i): if i <= 1: return i return i * self.fact_py(i-1) # convert the extension function into a unbound method # and attach it to the class import new X.fact_c = new.instancemethod(module.fact_c, None, X) # do a little benchmark import time start = time.clock() print "fib_py(30) =", fib_py(30), "%s seconds" % (time.clock() - start) start = time.clock() print "fib_c(30) =", fib_c(30), "%s seconds" % (time.clock() - start) x = X() start = time.clock() print "x.fact_py(12) =", x.fact_py(12), "%s seconds" % (time.clock() - start) start = time.clock() print "x.fact_c(12) =", x.fact_c(12), "%s seconds" % (time.clock() - start) |
From: Ken S. <ksi...@tt...> - 2001-08-28 21:55:13
|
> This is very cool. Can it (internally, at least) just be called "inline" or > "Inline" though? There's no particular need to distinguish it from Perl's > Inline module within the scope of Python programs, is there? No, there really isn't any need to call the module PyInline. However, I didn't want to call the project Inline because that would conflict with Brian's work and to call the module something different than the project would perhaps be confusing.. Thoughts?? > Were you able to leverage any of the techniqueus used in Brian Ingerson's > work? I looked at Brian's Inline to figure out PyInline's high level design and also to figure out how one builds arbitrary chunks of "anonymous" code (i.e., one idea is to build the code in a subdirectory which has in its name the MD5 checksum of the code). Brian's Inline also provides a few abstractions which I will be adding to PyInline in future. In particular, PyInline currently only supports C. In order to support the addition of more languages, I need to abstract out the concept of building an arbitrary chunk of code in some language and then "binding" to it. TTUL Ken |