oldmansaur
oldmansaur

Reputation: 163

Cython compile error C-Libraries Tutorial

I am currently trying to learn Cython, and started by going through their Tutorial. (Running Debian 8) I am running into problems in the Using C libraries part.

Here are my setup.py

from distutils.core import setup 
from distutils.extension import Extension 
from Cython.Build import cythonize

ext_modules = cythonize([
    Extension("queue", ["que.pyx"],
              libraries=["calg"])
    ])


setup(
      ext_modules=ext_modules )

que.pxd

cdef extern from "libcalg/queue.h":
    ctypedef struct Queue:
        pass
    ctypedef void* QueueValue

    Queue* queue_new()
    void queue_free(Queue* queue)

    int queue_push_head(Queue* queue, QueueValue data)
    QueueValue  queue_pop_head(Queue* queue)
    QueueValue queue_peek_head(Queue* queue)

    int queue_push_tail(Queue* queue, QueueValue data)
    QueueValue queue_pop_tail(Queue* queue)
    QueueValue queue_peek_tail(Queue* queue)

    bint queue_is_empty(Queue* queue)

and que.pyx

cimport que

cdef class Queue:
    cdef que.Queue* _c_queue
    def __cinit__(self):
        self._c_queue = que.cqueue_new()
        if self._c_queue is NULL:
            raise MemoryError()

def __dealloc__(self):
    if self._c_queue is not NULL:
        cqueue.queue_free(self._c_queue)

When I try to do python setup.py build_ext -i it tells me the following error messages: Compiling que.pyx because it changed.

[1/1] Cythonizing que.pyx

Error compiling Cython file:
------------------------------------------------------------
...
cimport que

cdef class Queue:
    ^
------------------------------------------------------------

que.pyx:3:5: 'Queue' redeclared 

Error compiling Cython file:
------------------------------------------------------------
...
cimport que

cdef class Queue:
    cdef que.Queue* _c_queue
                 ^
------------------------------------------------------------

que.pyx:4:18: Pointer base type cannot be a Python object

Error compiling Cython file:
------------------------------------------------------------
...
cimport que

cdef class Queue:
    cdef que.Queue* _c_queue
    def __cinit__(self):
        self._c_queue = que.cqueue_new()
                                     ^
------------------------------------------------------------

que.pyx:6:38: Cannot convert Python object to 'Queue *'

Error compiling Cython file:
------------------------------------------------------------
...
cimport que

cdef class Queue:
    cdef que.Queue* _c_queue
    def __cinit__(self):
        self._c_queue = que.cqueue_new()
                                     ^
------------------------------------------------------------

que.pyx:6:38: Storing unsafe C derivative of temporary Python reference

Error compiling Cython file:
------------------------------------------------------------
...
        self._c_queue = que.cqueue_new()
        if self._c_queue is NULL:
            raise MemoryError()

def __dealloc__(self):
    if self._c_queue is not NULL:
                    ^
------------------------------------------------------------

que.pyx:11:21: Invalid types for 'is_not' (Python object, void *)

Error compiling Cython file:
------------------------------------------------------------
...
        if self._c_queue is NULL:
            raise MemoryError()

def __dealloc__(self):
    if self._c_queue is not NULL:
        cqueue.queue_free(self._c_queue)
             ^
------------------------------------------------------------

que.pyx:12:14: undeclared name not builtin: cqueue
Traceback (most recent call last):
  File "setup.py", line 7, in <module>
    libraries=["calg"])
  File "/usr/local/lib/python2.7/dist-packages/Cython/Build/Dependencies.py", line 877, in cythonize
    cythonize_one(*args)
  File "/usr/local/lib/python2.7/dist-packages/Cython/Build/Dependencies.py", line 997, in cythonize_one
    raise CompileError(None, pyx_file)
Cython.Compiler.Errors.CompileError: que.pyx

To me it seems like the main problems are that I redeclare some things and that a pointer cannot be converted into a python object, but I really do not know what the exact problem is.

Can somebody help me make sense of the errors?

Upvotes: 0

Views: 1509

Answers (1)

DavidW
DavidW

Reputation: 30891

que.pyx and que.pxd share a namespace (if a pxd file has the same name as a pyx file then it's automatically cimported into the pyx file). Therefore Cython believes Queue to be both the C structure definition and your cdef class. (Under these circumstances you don't need to do cimport que)

You've got (at least) 3 options:

  1. Rename one of the files (so the automatic cimporting into the pyx namespace doesn't happen).
  2. Rename your cdef class.
  3. Rename your C struct. Note that you only need to do this in Cython, you can have keep the name in C:

Code for point 3:

ctypedef struct c_Queue "Queue": # called c_Queue in Cython but Queue in C
    pass

You then end up with a bunch of minor error messages:

que.pyx:6:38: Cannot convert Python object to 'Queue *'

Check the spelling of que.cqueue_new()

que.pyx:11:21: Invalid types for 'is_not' (Python object, void *)

You can't use is not for C pointers. Use !=

que.pyx:12:14: undeclared name not builtin: cqueue

Check the spelling.

Upvotes: 1

Related Questions