Newbie problem compiling cython

1,787 views
Skip to first unread message

Paul Boyle

unread,
Aug 20, 2019, 9:05:26 AM8/20/19
to cython-users
Hi,

I have small and old piece of ANSI C code which I want to wrap using Cython so that it is callable from Python.  I am trying to follow the examples given in Kurt Smith's book, "Cython: A Guide for Python Programmers".  However, I am getting compilation errors which I can't figure out.  Below is a paste of the errors and I am attaching  the 'chemical_element.pyx' file.  I would appreciate any help.  Thanks.  I am using Cython 0.28.4 which has been installed using pip into the Python 3.6.8 which comes with Linux CENTOS 7. My setup.py file looks like this:

setup.py
from distutils.core import setup, Extension
from Cython.Build import cythonize

ext = Extension( name = 'chemical_element', sources = ['chemical_element_c.c', 'chemical_element.pyx'])
setup(extension_modules=cythonize(ext))

Here is how I invoke the compilation:

python3 setup.py build_ext --inplace
Compiling chemical_element.pyx because it changed.
[1/1] Cythonizing chemical_element.pyx

Error compiling Cython file:
------------------------------------------------------------
...
        double atomic_weight

    int lookup_element_by_name( chemical_element *e, char *name )
    int lookup_element_by_z( chemical_element *e, int z )
   
    def get_element_by_name( char *elem_symb ):
   ^
------------------------------------------------------------

chemical_element.pyx:15:4: Expected an identifier, found 'def'

Error compiling Cython file:
------------------------------------------------------------
...
        else:
           ret_val = None
   
        return ret_val
   
    def get_element_by_atomic_number( int atomic_num ):
   ^
------------------------------------------------------------

chemical_element.pyx:28:4: Expected an identifier, found 'def'

Traceback (most recent call last):
  File "setup.py", line 5, in <module>
    setup(extension_modules=cythonize(ext))
  File "/usr/local/lib64/python3.6/site-packages/Cython/Build/Dependencies.py", line 1026, in cythonize
    cythonize_one(*args)
  File "/usr/local/lib64/python3.6/site-packages/Cython/Build/Dependencies.py", line 1146, in cythonize_one
    raise CompileError(None, pyx_file)
Cython.Compiler.Errors.CompileError: chemical_element.pyx
boyle:/arse% python3
Python 3.6.8 (default, Apr 25 2019, 21:02:35)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-36)] on linux
Type "help", "copyright", "credits" or "license" for more information.
chemical_element.pyx

Robert Bradshaw

unread,
Aug 20, 2019, 3:35:24 PM8/20/19
to cython...@googlegroups.com
Is the def inside an extern block? Otherwise I'd need to see the full file (or at least more context) to know what the error is here.

--

---
You received this message because you are subscribed to the Google Groups "cython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cython-users...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/cython-users/fea01f08-5f37-4f0a-ae4a-32a822992ca4%40googlegroups.com.

Paul Boyle

unread,
Aug 21, 2019, 12:14:02 AM8/21/19
to cython-users
Yes,  I put the 'def' inside the extern block.  I'm pasting the .pyx file below:

cdef extern from "chemical_element_c.h":                                                                                             
                                                                                                                                     
    #int ELEM_SYMB_LEN                                                                                                               
                                                                                                                                     
    struct chemical_element:                                                                                                         
        char symbol[3]                                                                                                               
        int  atomic_number                                                                                                           
        double coval_radius                                                                                                            
        double atomic_weight                                                                                                           
                                                                                                                                           
    int lookup_element_by_name( chemical_element *e, char *name )                                                                          
    int lookup_element_by_z( chemical_element *e, int z )                                                                                  
                                                                                                                                           
    def get_element_by_name( char *elem_symb ):
        cdef chemical_element elem
        cdef int ret
   
        ret = lookup_element_by_name( &elem, elem_symb )
   
        if 0 == ret:
           ret_val = (elem.symbol, elem.atomic_number, elem.coval_radius, elem.atomic_weight)

        else:
           ret_val = None
   
        return ret_val
   
    def get_element_by_atomic_number( int atomic_num ):
        cdef chemical_element elem
        cdef int ret
   
        ret = lookup_element_by_z( &elem, atom_num )
        if 0 == ret:
           ret_val = (elem.symbol, elem.atomic_number, elem.coval_radius, elem.atomic_weight)

        else:
           ret_val = None
   
        return ret_val

On Tuesday, August 20, 2019 at 3:35:24 PM UTC-4, Robert Bradshaw wrote:
Is the def inside an extern block? Otherwise I'd need to see the full file (or at least more context) to know what the error is here.

To unsubscribe from this group and stop receiving emails from it, send an email to cython...@googlegroups.com.

Paul Boyle

unread,
Aug 21, 2019, 12:14:18 AM8/21/19
to cython-users
I took the 'def's outside of the extern block and the module compiled.  I cleaned up another couple bugs, added cython compiler directives c_string_type=str, c_string_encoding=ascii and everything seems to be working.  Thanks so much!  I was at a loss.

One thing I don't understand is that the parameters to by 'def' functions don't seem to need 'cdef' qualifiers.  So my code compiles with this:
def get_element_by_atomic_number( int atomic_num ):

but I get compilation errors if I use this:
def get_element_by_atomic_number( cdef int atomic_num ):

Is there someplace in the documentation which explains when bare C like declarations are used Cython code versus cdef qualified declarations?

Thanks again for your help.

Paul


On Tuesday, August 20, 2019 at 3:35:24 PM UTC-4, Robert Bradshaw wrote:
Is the def inside an extern block? Otherwise I'd need to see the full file (or at least more context) to know what the error is here.

To unsubscribe from this group and stop receiving emails from it, send an email to cython...@googlegroups.com.

Robert Bradshaw

unread,
Aug 22, 2019, 12:27:45 AM8/22/19
to cython...@googlegroups.com
On Tue, Aug 20, 2019, 9:14 PM Paul Boyle <paul.bo...@gmail.com> wrote:
I took the 'def's outside of the extern block and the module compiled.  I cleaned up another couple bugs, added cython compiler directives c_string_type=str, c_string_encoding=ascii and everything seems to be working.  Thanks so much!  I was at a loss.

One thing I don't understand is that the parameters to by 'def' functions don't seem to need 'cdef' qualifiers.  So my code compiles with this:
def get_element_by_atomic_number( int atomic_num ):

but I get compilation errors if I use this:
def get_element_by_atomic_number( cdef int atomic_num ):

Is there someplace in the documentation which explains when bare C like declarations are used Cython code versus cdef qualified declarations?

The cdef keyword is only needed for starting c declarations on new lines. Though I've never thought about it before, it's true that this is inconsistent with argument type declarations (and that does complicate the code there). They're also not needed for members of c structs where there's no possible ambiguity.

To unsubscribe from this group and stop receiving emails from it, send an email to cython-users...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/cython-users/ce52215d-1ed3-439f-a1b3-ea372dfef1d5%40googlegroups.com.

Jérôme Kieffer

unread,
Aug 22, 2019, 12:28:38 AM8/22/19
to cython...@googlegroups.com
On Tue, 20 Aug 2019 05:57:24 -0700 (PDT)
Paul Boyle <paul.bo...@gmail.com> wrote:

> Hi,
>
> I have small and old piece of ANSI C code which I want to wrap using Cython
> so that it is callable from Python. I am trying to follow the examples
> given in Kurt Smith's book, "Cython: A Guide for Python Programmers".
> However, I am getting compilation errors which I can't figure out. Below
> is a paste of the errors and I am attaching the 'chemical_element.pyx'
> file. I would appreciate any help. Thanks.

Hi Paul,

The two python functions you define should not be indented: they define
the wrapper hence the Python side of your library. The "cdef extern"
block contains the C-level definition you want to use from cython.

smth like that:

cdef extern from "chemical_element_c.h":
#[...]
int lookup_element_by_name( chemical_element *e, char *name )
int lookup_element_by_z( chemical_element *e, int z )

def get_element_by_name( char *elem_symb ):
[...]
return ret_val

def get_element_by_atomic_number( int atomic_num ):
[...]
return ret_val


HTH

Jérôme
Reply all
Reply to author
Forward
0 new messages