Extending Python: rewriting a single method in C

Jacek Generowicz jmg at ecs.soton.ac.uk
Tue Mar 13 04:29:03 EST 2001


jepler at inetnebr.com (Jeff Epler) writes:

> On 12 Mar 2001 11:13:51 +0000, Jacek Generowicz
>  <jmg at ecs.soton.ac.uk> wrote:
> >I have an object-oriented numerical code written in Python. It has
> >come to the stage where the speed of the code is seriously impeding
> >progress. Profiling reveals (surprise, surprise) that most of the time
> >is spent in only 2 methods.
> >
> >Is there any way of re-writing just these methods in C ?
> 
> It's easy to write a function in C.  Other posters have mentioned references 
> to documentation about doing this.

As I mentioned in my replies to Paul and Alex (which I inadvertently
sent by mail rather than through the NG) I know that this can be done,
but I specifically want to rewrite single class/instance methods . . .

> However, you cannot make a builtin function be a method of a class/instance.

Bummer.

> Instead, you could write:
> 
> from cmodule import fast_a, fast_b
> 
> class fastKlass(Klass):
> 	def a(self, int1, int2):
> 		fast_a(self, int1, int2)
> 	def b(self, int1, int2):
> 		fast_b(self, int1, int2)
> In fast_a and fast_b, you can get arguments by using the ParseTuple string
> "(Oii)" and then use PyObject_SetAttrString and PyObject_GetAttrString
> to store or retrieve attributes (including, if necessary, instance
> methods) from the instance by their name.

Perhaps it is appropriate to insert here the exchange between Alex and
myself:

JG> AM> JG> Could something along following lines work ?
JG> AM> JG> 
JG> AM> JG> Write a module called my_extensions containing a function called
JG> AM> JG> foo_bar.
JG> AM> JG> 
JG> AM> JG> import my_extensions
JG> AM> JG> 
JG> AM> JG> class foo:
JG> AM> JG>    bar = my_extensions.foo_bar
JG> AM> 
JG> AM> No, this does not work, because only python-function-objects, NOT
JG> AM> builtin-function-objects, are mutated into unbound methods when
JG> AM> they are attributes of a class-object.
JG> 
JG> Yes, I've noticed this after a bit of experimenting.
JG> 
JG> AM>  Note that the name
JG> AM> 'builtin function object' is a bit misleading, as it actually
JG> AM> describes any function _written in C_ (part of an extension).
JG> AM> 
JG> AM> What CAN work is more explicit delegation:
JG> AM> 
JG> AM> class foo:
JG> AM>     def bar(self, whatever, blahblah):
JG> AM>         return my_extensions.foo_bar(self, whatever, blahblah)
JG> 
JG> Yes, but I was trying to avoid the function call overhead
JG> (particularly as one of the functions I need to rewrite is very short
JG> indeed).

> Note that if there are *many* calls to the method, rather than each
> invocation taking a large amount of time,

Bingo, this is exactly the case for one of the methods.

> then this approach is not going to gain you much, since it actually
> *increases* the function-call overhead.

And here is what Alex had to say about this:

AM> > Yes, but I was trying to avoid the function call overhead
AM> > (particularly as one of the functions I need to rewrite is very short
AM> > indeed).
AM> 
AM> No way to do that -- the function call overhead is there even
AM> if you call directly from Python to the C extension. 

But isn't the function call overhead greater for calling python
functions than it is for calling the C extensions ?

AM> If the function/method is called from a few places, you might
AM> manually inline in there, maybe.

Not sure I understand what you mean exactly. Are you suggesting that I
call an extension function wherever I would previously have called and
instance method ?

How do I get at the members of a class in C if that class was defined
in python ?

JE> In fast_a and fast_b, you can get arguments by using the ParseTuple string
JE> "(Oii)" and then use PyObject_SetAttrString and PyObject_GetAttrString
JE> to store or retrieve attributes (including, if necessary, instance
JE> methods) from the instance by their name.

Is there an organized reference where I can find the specifications of
all these functions ?  All I have come across shows example code, but
no full descriptions of what can/must be done.

Maybe some kind soul could show me what the correct code for a minimal
extension type is ?

For example, I tried to write an extension type equivalent to

class foo:
    def __init__ ( self, a ):
	self.a = a
    def show ( self ):
	print a

My various attempts, almost work, but there is always something not
quite right.

Incidentally, why does the xxobject.c file in the Objects directory of the
Python distribution contain no initxxobject function ?

Jacek



More information about the Python-list mailing list