Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cython: how to make an python object as a property of cython class

I have a existing python class X and I want to do the followings:

from my_python_module import X
cdef class Y:
    cdef X test

But this does not work out of the box, the cdef only accepts C type, not a Python class. Any work-around ?

like image 594
w00d Avatar asked Jan 09 '14 05:01

w00d


2 Answers

I don't think you can (http://docs.cython.org/src/userguide/sharing_declarations.html#sharing-extension-types) but you can work-around it using __cinit__ to assert that the attribute has the correct type. The declaration cdef public object x of the extension type attribute has the following meaning:

  • cdef is used to declare attributes of Cython extension types
  • public makes the attribute accessible from Python code
  • object is the type of the attribute, and means that it is a Python object
  • x is the identifier of the attribute

In your Cython file (named "p.pyx" for example):

import my_python_module as q

cdef class Y:
    cdef int i
    cdef public object x  # public so it can be accessed from Python

    def __cinit__(self, x_):
        assert isinstance(x_, q.X)
        self.x = x_

and my_python_module.py is where you have defined your class X:

class X(object):
    def __init__(self):
        self.i = 1

Then, you use it like this:

import my_python_module as q
import p

y = p.Y(q.X())
print y.x
print y.x.i

Also, note that cpdef means the same as cdef as of cython == 0.29.22, and will not be supported in cython == 3 (Cython issue 3959, and the warning that cython == 0.29.22 prints if an attribute is declared with cpdef; see also the changelog entry for that Cython version).

like image 188
lbolla Avatar answered Nov 20 '22 15:11

lbolla


I would use something like this:

cdef class SomeCls:
    cdef object _x

    def __cinit__(self, x_):
        self._x = x_

    property x:
        def __get__(self):
            return self._x
        def __set__(self, x_):
            self._x = x_

The above is especially useful when exposing attributes of an extern struct or class. Refer to example here: wrapping C++

like image 43
Al Conrad Avatar answered Nov 20 '22 13:11

Al Conrad