Domanda

I'm new to Cython and trying to speed up my kivy mobile game by using Cython code in critical AI module. My code goes as follows:

import numpy as np
cimport numpy as np

 #not relevant parts

cdef np.ndarray posarr
cdef np.int poslast = 0
cdef np.int posidx = 0

def posarr_init(np.ndarray pawnpos, np.int act):
    poslast = 0
    # not relevant, but referencing poslast

 #not relevant, but including function where poslast is referenced (not assigned)

def consider_pawn(np.int x, np.int y):
    cdef np.int pact, posx, posy, resx, resy
    cdef np.int p
    cdef np.int found = 0
    #not relevant

    #in the code there is this line, posx and posy are local variables
                    posarr[poslast, posx, posy] = posarr[posidx, posx, posy]

Here Cython gives me this error during compilation:

Error compiling Cython file:

------------------------------------------------------------
...
                pact = 1
        if pact == 1:
            #pawn is active, create child position
            for posx in range(11):
                for posy in range(11):
                    posarr[poslast, posx, posy] = posarr[posidx, posx, posy]
                                 ^
------------------------------------------------------------

position.pyx:98:34: local variable 'poslast' referenced before assignment

I can see that Cython compilation errors are reported in the same order that they appear in the code. My questions are:

Why does Cython consider poslast a local variable?

Why didn't it consider it a local variable in previous functions?

The generated C file is empty, it has only a message that it shouldn't be used inside. Is there a way to force Cython to leave the C code in the file even if there is a compilation error? Maybe looking into this file would help me understand the error messages (i.e. why this variable is considered local)...

È stato utile?

Soluzione

Short answer

Use the global statement to explicitly declare poslast as global in every function that writes to it.

Long answer

Cython follows Python binding rules: if a name is assigned anywhere in the function, it is assumed to be a local variable, unless you explicitly declare it global.

I guess that you perform and assignment to poslast after your example loop, which makes it an implicitly declared local variable (of type object). The loop then appears to use this yet uninitialized local.

Your posarr_init functions is similarly incorrect. It assigns implicitly declared local poslast without ever touching the global.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top