[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