I could list everything I've tried, but it always ends up conflicting with the Python 'raise' keyword.
There is a strange definition in libc/signal.pxd:
int raise_"raise" (int signum)
but I can't figure how to cimport and use it.
The whole point of renaming the function to raise_ is to avoid the name clash with python's keyword raise.
In python call the used name should be raise_, in the C-code produced by Cython the name will be raise (but there is no longer a conflict with Python keywords).
I.e. it can be used as follow:
%%cython
from libc.signal cimport raise_
...
raise_(1)
Related
I am working at understanding the petsc4py sources. In them one finds many ctypedef declarations of the following form:
ctypedef <type> <typename> "<C typename>"
for instance the following:
ctypedef char* PetscMatType "const char*"
or
ctypedef struct PetscMatStencil "MatStencil":
PetscInt k,j,i,c
(In this second case MatStencil is a type that will be known to C at compile time because of its definition in a PETSc header file.)
I have not been able to find any explanation in the Cython documentation that explains this use of a quoted string in a ctypedef statement. (I gather from context that it is a hint to cythonize to implement the Cython type being defined with the named C type.) Can anyone tell me where to find this documented?
More generally, is there anywhere a comprehensive Cython reference? The main documentation I know of is that at cython.readthedocs.io. This is helpful, but it is not a comprehensive reference. For instance, if you search it for ctypedef, you find a bunch of examples, but none of the syntax I asked about above. What you do not find there is a comprehensive definition of ctypedef syntax.
There isn't a document that's a more comprehensive reference than the documentation you linked. It actually does have what you're asking about in it, although I suspect you need to know what you're looking for to find it (unfortunately): https://cython.readthedocs.io/en/latest/src/userguide/external_C_code.html#resolving-naming-conflicts-c-name-specifications:
For special cases where namespacing or renaming on import is not enough, e.g. when a name in C conflicts with a Python keyword, you can use a C name specification to give different Cython and C names to the C function at declaration time. Suppose, for example, that you want to wrap an external C function called yield(). If you declare it as:
cdef extern from "myheader.h":
void c_yield "yield" (float speed)```
It then goes on to show other examples of structs and variables being renamed (but not specifically typedefs).
Essentially the assumption is that usually when you wrap something in Cython you want to use the same name in Cython as you do in C. However sometimes that doesn't work and this "quoted string" syntax lets you specify a different name that matches your C code.
It's a useful trick to know about because it often lets you work round Cython limitations - for example when wrapping a single variant of a heavily templated C++ class without exposing the whole template hierarchy. In these cases I suspect that the const in const char was confusing Cython, and that the author wanted to use MatStencil as the name in the Python interface (so needed a different name for the C interface). Lying to Cython about small details is often helpful...
I have two cython files:
intern.pxd
cdef int test = 8
extern.pyx
cimport intern
cpdef enum test_enum:
test = intern.test
If I try to compile this, It throws the following error:
Error compiling Cython file:
------------------------------------------------------------
...
cimport intern
cpdef enum test_enum:
test = intern.test ^
------------------------------------------------------------
side_tests\extern.pyx:4:17: Not allowed in a constant expression
I guess this is because the value of intern.test can not be known at compile time. I would like to get a solution for this. It is not an option to export the values of intern.pxd into extern.pyx because in the real project intern.pxd contains around 2000 external defined values/functions.
#DavidW pointed me to the working solution 'wrap in enum':
# In intern.pxd
cdef enum test_enum_intern:
test = 8
This works, but feels 'weird'. If somebody has another solution, he is welcome to post it.
I have a cython function:
def test(int a, int b):
return a+b
If I call it with:
test(0.5, 1)
I get the value 1.
Why doesn't it give a type error?
This is because float defines the special function __int__, which is called by Cython along the way (or more precise PyNumber_Long, at least this is my guess, because it is not easy to track the call through all these defines and ifdefs).
That is the deal: If your object defines __int__ so it can be used as an integer by Cython. Using Cython for implicit type-checking is not very robust.
If you want, you can check, whether the input is an int-object like in the following example (for Python3, for Python2 it is a little bit more complex, because there are different int-classes):
%%cython
from cpython cimport PyLong_Check
def print_me(i):
if not PyLong_Check(i):
print("Not an integer!")
else:
print(i)
In Cython, a class, or a extension type is a Python class, which means it can be initialized by Python. On the other hand, the parameters of its __init__ or __cinit__ have to be Python Object.
Is it possible to write a class in Cython, which can only be initilized by cdef functions, and thus can be initilized by C types and C++ objects?
I want to this because it would be easier to translate my existing Python codes to Cython code than C/C++ code.
You can quite easily create a class that can't (easily) be initialised from Python, but can only be created from a cdef factory function
cdef class ExampleNoPyInit:
cdef int value
def __init__(self):
raise RuntimeError("Cannot be initialise from python")
cdef ExampleNoPyInit_factory(int v):
cdef ExampleNoPyInit a
# bypass __init__
a = ExampleNoPyInit.__new__(ExampleNoPyInit)
a.value = v
return a
inst = ExampleNoPyInit_factory(5)
(I suspect the really committed could use the same method of initialising it in Python if they wanted. There are other ways to prevent initialisation if you want to be more thorough - for example you could use a cdef global variable in your Cython module as a flag, which would not be accessed from Python).
This class still has the Python reference counting mechanism built-in so is still a "Python class". If you want to avoid that then you could use a cdef struct, (although that can't have member functions).
c doesn't do bounds check. So how does cython do the check if it compiles to c?
%%cython --annotate
cimport cython
#cython.boundscheck(True)
cpdef myf():
cdef double pd[8]
for i in range(100):
pd[i] = 0
print pd[i]
The above code compiles to the same C code no matter whether I set True or False for boundscheck. And if I run myf() there is no warnings (it happens to not crash...).
Update
So cython doens't do bounds check on c arrays anyway.
http://docs.cython.org/src/reference/compilation.html#compiler-directives
"Cython is free to assume that indexing operations ([]-operator) in the code will not cause any IndexErrors to be raised. Lists, tuples, and strings are affected..."
I think in your code a C double array doesn't store its length anywhere, and so it's impossible for Cython to do any useful checks (except in your very trivial example). However, a built in Python type which can raise IndexErrors should be different (I'd assume numpy arrays, python arrays and cython memoryviews should also be affected since they all have a mechanism for Cython to tell if it's gone off the end).