[Pyrex] Adding custom statements to pyrex ? (or passing through macros to C files)

Michael Sparks zathras at thwackety.com
Sun Oct 3 23:18:14 CEST 2004


On Sun, 3 Oct 2004, Lenard Lindstrom wrote:
...
> File duff.h:
>
> #define Resume() switch (this->state) { default: this->state=__LINE__;
> #define Yield(x) this->state=__LINE__ ; return (x); case __LINE__ :
> #define Endresume() this->state=__LINE__; case __LINE__: break; }
>
>
> And now two Pyrex versions of Duffs_next using the above macros:
>
> File duff.pyx:
>
> cdef extern from "duff.pyx":
>     void Resume()
>     void Yield(int x)
>     void Endresume()
>
> cdef struct Duffs:
>    int state
>    int i
>    char * tag
>
> # Duffs_next that is all C
> cdef int Duffs_next(Duffs *this):
>     cdef int i
>     Resume()
>     for i from 0 <= i < 10:
>         this.i = i
>         Yield(0)
>     Endresume()
>
> # Duffs_next with some Python mixed in
> cdef Py_Duffs_next(Duffs *this):
>     cdef int i
>     Resume()
>     for i from 0 <= i < 10:
>         this.i = i
>         Yield(0)
>     Endresume()
>
> Finally the part of the Pyrex 0.9.3 output C file duff.c that defines the two
> versions of Duffs_next:
>
> static int __pyx_f_4duff_Duffs_next(struct __pyx_t_4duff_Duffs (*__pyx_v_this)) {
>   int __pyx_v_i;
>   int __pyx_r;
>
>   /* "C:\user\projects\python\Duffs\duff.pyx":14 */
>   Resume();
>
>   /* "C:\user\projects\python\Duffs\duff.pyx":15 */
>   for (__pyx_v_i = 0; __pyx_v_i < 10; ++__pyx_v_i) {
>
>     /* "C:\user\projects\python\Duffs\duff.pyx":16 */
>     __pyx_v_this->i = __pyx_v_i;
>
>     /* "C:\user\projects\python\Duffs\duff.pyx":17 */
>     Yield(0);
>     __pyx_L2:;
>   }
>   __pyx_L3:;
>
>   /* "C:\user\projects\python\Duffs\duff.pyx":18 */
>   Endresume();
>
>   __pyx_r = 0;
>   goto __pyx_L0;
>   __pyx_L1:;
>   __Pyx_WriteUnraisable("duff.Duffs_next");
>   __pyx_L0:;
>   return __pyx_r;
> }
>
> static PyObject *__pyx_f_4duff_Py_Duffs_next(struct __pyx_t_4duff_Duffs (*__pyx_v_this)) {
>   int __pyx_v_i;
>   PyObject *__pyx_r;
>
>   /* "C:\user\projects\python\Duffs\duff.pyx":23 */
>   Resume();
>
>   /* "C:\user\projects\python\Duffs\duff.pyx":24 */
>   for (__pyx_v_i = 0; __pyx_v_i < 10; ++__pyx_v_i) {
>
>     /* "C:\user\projects\python\Duffs\duff.pyx":25 */
>     __pyx_v_this->i = __pyx_v_i;
>
>     /* "C:\user\projects\python\Duffs\duff.pyx":26 */
>     Yield(0);
>     __pyx_L2:;
>   }
>   __pyx_L3:;
>
>   /* "C:\user\projects\python\Duffs\duff.pyx":27 */
>   Endresume();
>
>   __pyx_r = Py_None; Py_INCREF(__pyx_r);
>   goto __pyx_L0;
>   __pyx_L1:;
>   __Pyx_AddTraceback("duff.Py_Duffs_next");
>   __pyx_r = 0;
>   __pyx_L0:;
>   return __pyx_r;
> }
>
>
> Pyrex does not know that Yield() is inserting a return in the middle
> of the code. And Py_Duffs_next wants to return a Python object. The code
> will not compile.

This is very useful, thanks. The approach I was taking to wrap the macros
wasn't working the way I expected (and likewise wouldn't compile), but
yours is closer to what I was aiming for. One possible workaround this
might be to have a Yield and cYield maybe? I'll have a play. (I know it's
not an ideal solution, but I may as well try :)

Regards,


Michael.





More information about the Pyrex mailing list