Cython subclassing "First base of" ... "is not an extension type" even though it is defined with cdef

2 min read 06-10-2024
Cython subclassing "First base of" ... "is not an extension type" even though it is defined with cdef


Cython Subclassing Headache: "First base of" Error and How to Fix It

Problem: When attempting to subclass a Cython class in Cython, you might encounter an error like "First base of 'MyClass' is not an extension type" even though you clearly defined your base class with cdef. This can be incredibly frustrating, especially when you expect Cython's speed benefits from subclassing.

Rephrasing: Imagine you want to create a specialized type of object in Cython that inherits properties from a base class. You carefully define both classes with cdef to gain performance, but Cython throws an error, claiming your base class isn't an "extension type". This article will delve into why this error occurs and provide solutions for smoothly subclassing in Cython.

Scenario and Code:

Let's say you have a simple Cython base class "BaseClass" and a subclass "MyClass" attempting to inherit from it:

# my_module.pyx
cdef class BaseClass:
    cdef int value

    def __init__(self, int val):
        self.value = val

cdef class MyClass(BaseClass):
    cdef double extra_value

    def __init__(self, int val, double extra):
        BaseClass.__init__(self, val)
        self.extra_value = extra

When you try to compile and use this code, you might encounter the error:

'First base of 'MyClass' is not an extension type'

Analysis and Clarification:

The root cause of this error lies in Cython's strictness about inheritance. While you used cdef to define both BaseClass and MyClass, Cython requires the base class to be explicitly marked as an "extension type" for subclassing.

Solutions:

  1. Explicitly Mark the Base Class:

    • Add cdef cppclass before the base class declaration to mark it as an extension type.
    cdef cppclass BaseClass: 
        cdef int value
        ...
    
  2. Use object as the Base Class:

    • If you don't need the performance benefits of cdef for the base class, consider using Python's built-in object as the base class. This will work seamlessly with Cython subclassing.
    cdef class BaseClass(object):
        cdef int value
        ...
    

Examples:

Here's an example of how to fix the code using the first solution:

cdef cppclass BaseClass:
    cdef int value

    def __init__(self, int val):
        self.value = val

cdef class MyClass(BaseClass):
    cdef double extra_value

    def __init__(self, int val, double extra):
        BaseClass.__init__(self, val)
        self.extra_value = extra

Additional Value:

  • This error can occur in complex inheritance hierarchies as well. Always check if your base classes are marked as extension types if you're experiencing this error.
  • Understanding the difference between cdef class and cdef cppclass is essential for working with Cython inheritance effectively.

References and Resources:

Conclusion: By correctly defining your base classes as extension types in Cython, you can eliminate the "First base of" error and enjoy the performance benefits of subclassing in your Cython projects.