A note on cdef classes in .pxd files

If you are adding to / making an extension which includes .pxd files, such as the finesse.cmath extension, then there is a subtlety involving cdef classes with static-methods which you should be aware of. To demonstrate this take a class defined as follows in a .pxd file:

cdef class Math:
    @staticmethod
    cdef double degrees(double x) nogil

    @staticmethod
    cdef double radians(double x) nogil

    # ...

this will be compiled to the following .c code declaration:

struct __pyx_vtabstruct_5cmath_5cmath_Math {
    double (*degrees)(double);
    double (*radians)(double);
}

The important thing to note here is that the functions degrees and radians are stored as function pointers in a struct. As a result of this, you must define these methods in the .pyx file in the same order as they appear in the .pxd file. For example, the Math class in the .pyx file in this case must be:

cdef class Math:
    @staticmethod
    cdef double degrees(double x) nogil:
        return x * 180.0 / PI

    @staticmethod
    cdef double radians(double x) nogil
        return x * PI / 180.0

    # ...

If you defined these the other way around in the .pyx file (relative to the .pxd) then the extension would still compile but whenever, e.g., Math.degrees was used (from another extension for example) then Math.radians would actually be called instead leading to incorrect results and code which would be very difficult to debug!