0

I've started to look into Cython as a way to speed up some code. One thing I would like to do is create a Cython class, which seems to be represented as a struct, to help create clean code.

I have the following folder structure:
+ test_package
+-- a.pxd
+-- a.pyx
+ setup.py

a.pxd:

from libc.stdint cimport uint8_t

cdef class ClassA:
    cdef readonly:
        uint8_t a_attribute
        uint8_t b_attribute
        uint8_t c_attribute

    cdef uint8_t get_a(self)
    cdef uint8_t get_b(self)
    cdef uint8_t get_c(self)

a.pyx:

from libc.stdint cimport uint8_t

cdef class ClassA:
    def __cinit__(self):
        self.a_attribute = 0x00
        self.b_attribute = 0x01
        self.c_attribute = 0x02

    cdef uint8_t get_a(self):
        return self.a_attribute

    cdef uint8_t get_b(self):
        return self.b_attribute

    cdef uint8_t get_c(self):
        return self.c_attribute

cdef ClassA make_ClassA():
    cdef ClassA A = ClassA()
    A.a_attribute = 0x12
    return A

setup.py:

from setuptools import Extension, setup
from Cython.Build import cythonize


extensions = [Extension("test_package", ['test_package/*.pyx'])]

setup(
    ext_modules=cythonize(extensions, annotate=True),
    compiler_directives={'language_level' : "3"},
)

I can run python3.7 setup.py build_ext --inplace to build this. When I look at a.html I see something like this:

a.html

Is there a reason that it's being converted to Python objects? For instance:

self.a_attribute = 0x00
  if (__Pyx_PyObject_SetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_a_attribute, __pyx_int_0) < 0) __PYX_ERR(1, 5, __pyx_L1_error)

has the ability to reference __pyx_v_self, but still converts it to a Python object. I can get a lot of my methods to compile to C code, but my biggest concern is for something like this:

enter image description here

The i, j, k loops are compile to C, but the accessing of the struct variable is still a reference to a Python object.

Another option is I can do something like this:

enter image description here

But obviously this is still going to show as Python code based off everything I've shown above. So why is this? Am I using cdef class incorrectly or is this just what happens when accessing cdef class attributes?

Chrispresso
  • 3,660
  • 2
  • 19
  • 31
  • I cannot check now, but my guess is that your setup file is wrong and cython never sees the pxd file and knows nothing about cdef members. 1) The name of the module must be the same as of the pyx file (this is probably the reason for your problems) 2) you cannot put multiple pyx file in one module (*.pyx doesn’t make much sense) 3) if it is a package __init__.py is probably a good idea. – ead Apr 25 '20 at 19:43
  • @ead why can you not put multiple pyx files into one extension module? My end goal is to speed up 3 classes. I was planning to basically have `_.pyx` and `_.pxd` for `a, b, c`. Is it not possible to combine all of those into `test_package.so`? Will I need a `.so` for each pyx? – Chrispresso Apr 25 '20 at 22:31
  • FYI: https://stackoverflow.com/q/30157363/5769463 – ead Apr 26 '20 at 08:43

0 Answers0