cython / cython

The most widely used Python to C compiler
https://cython.org
Apache License 2.0
9.43k stars 1.48k forks source link

Pointer types don't work properly with template functions #534

Open empyrical opened 8 years ago

empyrical commented 8 years ago

Instantiating a template class like so works fine in Cython:

new MyClass[int *]()

However, this gives a syntax error:

cdef extern from "foo.h":
    T my_function[T]()

my_function[int *]()

Error compiling Cython file:
------------------------------------------------------------
...
cdef extern from "foo.h":
    T my_function[T]()

my_function[int *]()                ^
------------------------------------------------------------

foo.pyx:4:17: Expected an identifier or literal

A small workaround I've been using is making a ctypedef like so:

ctypedef int* intptr
my_function[intptr]()
empyrical commented 8 years ago

It doesn't seem as if it's just template functions that encounter this - it's also template classes if they're being used outside of a cdef statement, like:

from libcpp cimport bool
cdef extern from *:
    cdef cppclass MyClass[T]:
        MyClass()
        MyClass(bool someArgument)        
        @staticmethod
        void aMethod()

# Okay
cdef MyClass[int *] myvar

# Not okay
cdef MyClass[int *] myvar = MyClass[int *](True)

# Not okay
MyClass[int *].aMethod()
navytux commented 5 years ago

I've hit this too:

Error compiling Cython file:
------------------------------------------------------------
...
# cython: language_level=2
cdef extern from "golang.h" nogil:
    void *makechan[T](unsigned size)

cdef void *a = makechan[int*](10)
                           ^
------------------------------------------------------------

y.pyx:5:28: Expected an identifier or literal
Traceback (most recent call last):
  File "/home/kirr/src/wendelin/venv/z-dev/bin/cythonize", line 11, in <module>
    load_entry_point('Cython', 'console_scripts', 'cythonize')()
  File "/home/kirr/src/tools/py/cython/Cython/Build/Cythonize.py", line 223, in main
    cython_compile(path, options)
  File "/home/kirr/src/tools/py/cython/Cython/Build/Cythonize.py", line 106, in cython_compile
    **options.options)
  File "/home/kirr/src/tools/py/cython/Cython/Build/Dependencies.py", line 1096, in cythonize
    cythonize_one(*args)
  File "/home/kirr/src/tools/py/cython/Cython/Build/Dependencies.py", line 1219, in cythonize_one
    raise CompileError(None, pyx_file)

Fails with both 0.29.x and current master (0.29.12-519-gba6d2c5e6)

With just makechan[int](10) (no star after int) it works.

pushkarnimkar commented 5 years ago

Yet another case

cdef extern from "../../cpp/complex_object/complex_object.h":

    ctypedef struct ComplexReturnType:
        cpp_map[string, vector[int]*]* index
                                   ^
------------------------------------------------------------

cython/complex_object/complex_object.pxd:9:36: Expected an identifier or literal
robertwb commented 5 years ago

Generally if we know that we're parsing a type, there is special code to resolve the "dangling" star as part of the (possibly empty) declarator, but in cases where we expect an expression it is first parsed as a valid Python expression in which case the * is interpreted as multiplication. This is tricky to resolve; until then using a typedef is the best solution.

leofang commented 2 days ago

It's quite surprising that templating with pointer types requires an extra ctypedef, which kinda defeats the purpose of templating in the first place. If I have to add ctypedefs to all of the supported types, a simple template instantiation requires a lot of boilerplate code... 😢