1

Effectively, I am cleaning up a cython module that has many globally scoped functions and variables. I thought cdef classes would be a great way to package some of these functions. But I ran into an issue when trying to call some of the methods of these classes. I boilded it down to these two examples that show my issue. The functionality of the code is unimportant, I am just trying to demonstrate the problem I am facing.

cdef class Foo:
    def __init__(self):
        pass

    cdef int deref(self, int *bar):
        return bar[0]

cdef int bar = 5
foo = Foo()
foo.deref(&bar)

If I run this code I get an error

Cannot convert 'int *' to Python object

But If I define everything in global scope it works just fine:

cdef int deref(int *bar):
    return bar[0]
cdef int bar = 5
deref(&bar)

My question is: Is it possible to call a cdef method in this mannor?

My thought was that it would work since it is all being done within cython, but for some reason cython wants to convert the pointer into a python object and then back into a cython object? Is this always the case? I thought cdef classes were an effective tool to use when using cython.

Anyways, I have exhausted my attempts at solving this issue myself and wanted to ask here before abandoning cdef classes and going back to functional programming.

2
  • 1
    There is no foo. If you use Foo, it should be Foo().deref(&bar) and it works. Commented Sep 22, 2020 at 13:52
  • 1
    You are right, I edited the code to add a foo = Foo() I see the problem, I need to define foo like: cdef Foo foo = Foo() Otherwise it is a python object. If you answer in a post I will :check: it :) @ead Commented Sep 22, 2020 at 14:09

2 Answers 2

0

Normally Cython would detect the cdef type of a variable, e.g. for

def doit():
    cdef int bar = 5
    foo = Foo()
    return foo.deref(&bar)

Cython would see, that foo is of type cdef Foo and treat it as such (the above code builds).

Not so for the global variables:

foo = Foo()

this is implicitly a def variable, which can be accessed (or set) via modulename.foo. That means, Cython cannot be sure, that foo is of type Foo - it could be set to int, float and what not.

Thus Cython must assume that foo is a pure Python-object with a (def-) method called deref which has Python arguments, and a pointer cannot be cast to a Python object automatically - which leads to the error you are observing.

Declaring foo as

cdef Foo foo=Foo()

hides the variable from pure-python, so it is no longer possible to access it via modulename.foo and to assign some arbitrary object to it. Thus it possible for Cython to assume, that foo is really of type Foo, thus granting access to cdef-functions of the class Foo.

Sign up to request clarification or add additional context in comments.

Comments

0

foo must be declared a Foo object

cdef Foo foo = Foo()

Then all is well

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.