[Pyrex] [Cython-dev] where is Cython 'cpdef'

Robert Bradshaw robertwb at math.washington.edu
Wed Oct 31 17:22:05 CET 2007


On Oct 31, 2007, at 12:57 AM, David McNab wrote:

> On Tue, 2007-10-30 at 23:31 -0700, Robert Bradshaw wrote:
>>> Can you please point me to the version/branch of cython that has  
>>> cpdef
>>> support?
>
>> I'm going to be releasing that branch later tonight/tomorrow, it
>> looks like in the current repository it's still called rdef.
>
> Hi,
>
> Will the new 'cpdef' keyword do the same as the current 'rdef'?

Yes.

> I tried out 'rdef' from the current repo, and it is indeed creating a
> 'C' and a 'Python' verion of the same method. But I notice that the
> generated C method seems to carry a lot of Python baggage.

True, but it is a fixed amount of baggage on (in your case) a tiny  
function. More importantly, the whole block is surrounded by

if (unlikely(((PyObject *)__pyx_v_self)->ob_type->tp_dictoffset != 0)) {
...
}

so it won't get executed for cdef classes (and this test is very fast).

- Robert



>
> Consider:
>
>     rdef int area(self):
>         return self.width * self.height
>
> This generates:
>
> ----------------------------------
> /*
>  * not-so-thin C method
>  */
>
> static PyObject *__pyx_f_py_6myshit_4Rect_area(PyObject *__pyx_v_self,
> PyObject *unused); /*proto*/
> static  int __pyx_f_6myshit_4Rect_area(struct __pyx_obj_6myshit_Rect
> *__pyx_v_self) {
>   int __pyx_r;
>   PyObject *__pyx_1 = 0;
>   PyObject *__pyx_2 = 0;
>   int __pyx_3;
>   Py_INCREF(__pyx_v_self);
>   if (unlikely(((PyObject *)__pyx_v_self)->ob_type->tp_dictoffset ! 
> = 0))
> {
>     __pyx_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self),
> __pyx_n_area); if (unlikely(!((PyObject *)__pyx_v_self)))
> {__pyx_filename = __pyx_f[0]; __pyx_lineno = 11; goto __pyx_L1;}
>     if (!(strcmp(__pyx_1->ob_type->tp_name,
> "builtin_function_or_method") == 0) ||
> (PyCFunction_GET_FUNCTION(__pyx_1) !=  
> &__pyx_f_py_6myshit_4Rect_area)) {
>       __pyx_2 = PyObject_CallObject(__pyx_1, 0); if (unlikely(! 
> __pyx_2))
> {__pyx_filename = __pyx_f[0]; __pyx_lineno = 11; goto __pyx_L1;}
>       Py_DECREF(__pyx_1); __pyx_1 = 0;
>       __pyx_3 = PyInt_AsLong(__pyx_2); if (unlikely((__pyx_3 == -1) &&
> PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 11;  
> goto
> __pyx_L1;}
>       Py_DECREF(__pyx_2); __pyx_2 = 0;
>       __pyx_r = __pyx_3;
>       goto __pyx_L0;
>     }
>   }
>   __pyx_r = (__pyx_v_self->width * __pyx_v_self->height);
>   goto __pyx_L0;
>
>   __pyx_r = 0;
>   goto __pyx_L0;
>   __pyx_L1:;
>   Py_XDECREF(__pyx_1);
>   Py_XDECREF(__pyx_2);
>   __Pyx_WriteUnraisable("myshit.Rect.area");
>   __pyx_L0:;
>   Py_DECREF(__pyx_v_self);
>   return __pyx_r;
> }
>
> /*
>  * thin-ish Python wrapper method
>  */
>
> static PyObject *__pyx_f_py_6myshit_4Rect_area(PyObject *__pyx_v_self,
> PyObject *unused); /*proto*/
> static PyObject *__pyx_f_py_6myshit_4Rect_area(PyObject *__pyx_v_self,
> PyObject *unused) {
>   PyObject *__pyx_r;
>   PyObject *__pyx_1 = 0;
>   Py_INCREF(__pyx_v_self);
>   __pyx_1 = PyInt_FromLong(((struct __pyx_vtabstruct_6myshit_Rect
> *)((struct __pyx_obj_6myshit_Rect
> *)__pyx_v_self)->__pyx_vtab)->area(((struct __pyx_obj_6myshit_Rect
> *)__pyx_v_self))); if (unlikely(!__pyx_1)) {__pyx_filename = __pyx_f 
> [0];
> __pyx_lineno = 11; goto __pyx_L1;}
>   __pyx_r = __pyx_1;
>   __pyx_1 = 0;
>   goto __pyx_L0;
>
>   __pyx_r = Py_None; Py_INCREF(Py_None);
>   goto __pyx_L0;
>   __pyx_L1:;
>   Py_XDECREF(__pyx_1);
>   __Pyx_AddTraceback("myshit.Rect.area");
>   __pyx_r = 0;
>   __pyx_L0:;
>   Py_DECREF(__pyx_v_self);
>   return __pyx_r;
> }
> ------------------------
>
> Compare this to the other approach, of defining 2 methods:
>
>     cdef int _area(self):
>         return self.width * self.height
>
>     def area(self):
>         return self._area()
>
> which generates:
>
> --------------------------------------
> /* thin C version */
>
> static  int __pyx_f_6myshit_4Rect__area(struct __pyx_obj_6myshit_Rect
> *__pyx_v_self) {
>   int __pyx_r;
>   Py_INCREF(__pyx_v_self);
>   __pyx_r = (__pyx_v_self->width * __pyx_v_self->height);
>   goto __pyx_L0;
>   __pyx_r = 0;
>   __pyx_L0:;
>   Py_DECREF(__pyx_v_self);
>   return __pyx_r;
> }
>
> /* Python wrapper method */
>
> static PyObject *__pyx_f_py_6myshit_4Rect_area(PyObject *__pyx_v_self,
> PyObject *unused); /*proto*/
> static PyObject *__pyx_f_py_6myshit_4Rect_area(PyObject *__pyx_v_self,
> PyObject *unused) {
>   PyObject *__pyx_r;
>   PyObject *__pyx_1 = 0;
>   Py_INCREF(__pyx_v_self);
>   __pyx_1 = PyInt_FromLong(((struct __pyx_vtabstruct_6myshit_Rect
> *)((struct __pyx_obj_6myshit_Rect
> *)__pyx_v_self)->__pyx_vtab)->_area(((struct __pyx_obj_6myshit_Rect
> *)__pyx_v_self))); if (unlikely(!__pyx_1)) {__pyx_filename = __pyx_f 
> [0];
> __pyx_lineno = 18; goto __pyx_L1;}
>   __pyx_r = __pyx_1;
>   __pyx_1 = 0;
>   goto __pyx_L0;
>   __pyx_r = Py_None; Py_INCREF(Py_None);
>   goto __pyx_L0;
>   __pyx_L1:;
>   Py_XDECREF(__pyx_1);
>   __Pyx_AddTraceback("myshit.Rect.area");
>   __pyx_r = 0;
>   __pyx_L0:;
>   Py_DECREF(__pyx_v_self);
>   return __pyx_r;
> }
> ------------------------------------
>
> Any words of wisdom on this?
>
> Cheers
> David
>
>
>
> _______________________________________________
> Cython-dev mailing list
> Cython-dev at lists.berlios.de
> https://lists.berlios.de/mailman/listinfo/cython-dev




More information about the Pyrex mailing list