Hi, I think maybe I've seen this brought up once or twice before in the past, but with no real discussion. There is a slightly unpythonic problem with using cpdef inline functions defined in a .pxd file that happen to access global variables. For example:
$ cat foo.pxd FOO_A = 1 cpdef inline foo(): return FOO_A $ cat bar.pyx from foo cimport foo print(foo()) Running this like python -c 'import bar' results in: Traceback (most recent call last): File "<string>", line 1, in <module> File "bar.pyx", line 3, in init bar print(foo()) File "foo.pxd", line 4, in foo.foo return FOO_A NameError: name 'FOO_A' is not defined Of course, if the function "foo" were not inlined this would work fine. But the inlining really breaks things, I think, in an unpythonic way. I could be misunderstanding how Cython's "inline" should be interpreted but I feel like it's an implementation detail that should not fundamentally change how the code in that function works. There are a couple issues here. First of all, if a .pxd file exists but not a .pyx, no actual module will be created. This is by design of course, but in this case either, inlined functions in a .pxd module should be prohibited from accessing globals, or a trivial module should be created to store the globals for that module. The second problem boils down to the global variable lookup being compiled to something like: __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_FOO_A) Perhaps, when a function from one module gets inlined in another module, at least in the case where it needs to access globals, the originating module should be imported first and __Pyx_GetModuleGlobalName replaced with an equivalent that uses the originating module's globals. So have a global variable like static PyObject* __pyx_d_foo and in the module init code something like: _pyx_t_1 = __Pyx_Import("foo") __pyx_d_foo = PyModule_GetDict(__pyx_t_1) then in the inlined function, replace the call to __Pyx_GetModuleGlobalName to an equivalent that uses __pyx_d_foo instead of __pyx_d. This all assumes, of course, that "foo" is an importable module. I'm not sure this makes sense otherwise... If not then maybe inlining a function should also "inline" any global variables it uses. Thoughts? Erik _______________________________________________ cython-devel mailing list cython-devel@python.org https://mail.python.org/mailman/listinfo/cython-devel