Reputation: 207
I want to share the declaration of one class which is the member data of another class in cython using the share of declaration for extension types.
This is the python wrapper (run.py
) that is run by user. It declares a Solver
class.
#! /usr/bin/env python
# filename: run.py
import Solver
S = Solver.Solver()
Result = S.Solve()
The Solver
object has a cpdef Solve()
member function which is called once from the python part of the code. The Solver
class has cdef object Computation
member data:
# filename: Solver.pyx
from Computation cimport Computation
cdef class Solver:
cdef object Comp
def __cinit__(self):
self.Comp = Computation()
cpdef double Solve(self):
Result = self.Comp.Add(4)
return Result
The Computation
class is merely a cython code:
# filename: Computation.pxd
cdef class Computation:
cdef int a
cdef double Add(self,double b)
and
# filename: Computation.pyx
cdef class Computation:
def __cinit__(self):
self.a = 3
cdef double Add(self,double b):
return self.a + b
The setup.py
is:
# filename: setup.py
from distutils.core import setup
from Cython.Build import cythonize
setup(
package_data = {"Computation": ["Computation.pxd"]},
ext_modules = cythonize(["*.pyx"],include_path=["."]),
)
Solver.Solve()
calls Computation.Add()
many times, but here I suppressed the for
loops for simplicity. The point is that calling Add()
should have the minimal cost, hence I have declared it with cdef
.
All files are in the same directory. I compile with python setup build_ext --inplace
. Then by running ./run
I receive the following error:
Exception AttributeError: "'Computation.Computation' object has no attribute 'Add'" in 'Solver.Solver.Solve' ignored
I have two ways to get around with this:
Add()
from a cdef
to a cpdef
function I no longer get this error. But in this case, the Solve()
calls a cpdef
which has an overhead compared to cdef
. I want to avoid using cpdef
for Add()
, since in the actual code, Add()
is an expensive code and is called may times.If in the Solver
class, I do not declare Comp
object as a member data, rather just declare it inside the Solve()
function, I do not get this error. Something like this:
# filename: Solver.pyx
from Computation cimport Computation
cdef class Solver:
# No member data here.
cpdef double Solve(self):
# We declare Comp here instead:
Comp = Computation()
Result = Comp.Add(4)
return Result
But I prefer the Comp
to be a member of Solver
as well. My guess is that by declaring Comp
in a python code def __cinit__(self)
, the cdef
functions are not declared anymore.
So, my question is that how can I share declaration of an extension type which itself is a member data of another class? That is, how a cython extension type can be declared in __cinit__()
?
Upvotes: 1
Views: 345
Reputation: 207
Found it myself. Simply in Solver.pyx
the line
cdef object Comp
should be changed to
cdef Computation Comp
which here the object is explicitly typed.
With this the extension type's cdef
method can be accessed elsewhere.
Upvotes: 1