Skip to content

Py_buffer builtin struct unusable after 0.27.0 #2046

Closed
@klaussfreire

Description

@klaussfreire

Since 0.27.1, declaring Py_buffer variables in pure-python mode ceased working. This applies to 0.27.1, 0.27.2 and 0.27.3.

import cython

@cython.locals(pybuf = 'Py_buffer')
def f():
    return cython.cast(int, cython.address(pybuf))

print f()

I know this isn't really useful code, but it illustrates the issue with a minimal example. I'm getting this error in actual working (with 0.27.0) code.

When compiling with cython 0.27.2 (and .3), gives:

(cython)claudiofreire@klaumpptophp:~> cython buffer_bug.py

Error compiling Cython file:
------------------------------------------------------------
...
import cython

@cython.locals(pybuf = 'Py_buffer')
                      ^
------------------------------------------------------------

buffer_bug.py:3:23: Not a type

Error compiling Cython file:
------------------------------------------------------------
...
import cython

@cython.locals(pybuf = 'Py_buffer')
def f():
    return cython.cast(int, cython.address(pybuf))
                                          ^
------------------------------------------------------------

buffer_bug.py:5:43: undeclared name not builtin: pybuf

Error compiling Cython file:
------------------------------------------------------------
...
import cython

@cython.locals(pybuf = 'Py_buffer')
def f():
    return cython.cast(int, cython.address(pybuf))
                                 ^
------------------------------------------------------------

buffer_bug.py:5:34: Taking address of non-lvalue (type Python object)

In cython 0.27.0, however, it builds correctly, generating the following code:

  __pyx_t_1 = __Pyx_PyInt_From_int(((int)(&__pyx_v_pybuf))); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 5, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;

I could find no directly relatable changes in the commit history, but I'm not that familiar with this code, so maybe someone else can figure this out.

To clarify, in non-pure-python mode it works correctly:

from cpython cimport Py_buffer

def f():
    cdef Py_buffer pybuf
    return <int>&pybuf

print f()

Compiles in all versions.

Adding the cimport to buffer_bug.pxd in pure-python mode doesn't change a thing.

FTR, I realize Py_buffer is unusable in pure python. The use case for this always involves compiled-only code paths:

if cython.compiled:
    # do something with Py_buffer
else:
    # do it the slower pure-python way

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions