Cython无法导入和执行函数:存储临时Python引用的不安全C派生

Cython无法导入和执行函数:存储临时Python引用的不安全C派生,python,cython,cythonize,Python,Cython,Cythonize,我是Cython的新手,只是想尝试一个简单的脚本。我无法从模块导入函数并在另一个文件中使用它,但是如果我在同一个文件中声明该函数,它就可以正常工作。这里可能有什么问题。我错过什么了吗 这是原始代码段(test_cy.pyx): 我可以像(编译后)那样运行它: 但是,如果我将say_hello函数移动到另一个文件(utils.pyx): 。。。并将其导入我的原始test_cy.pyx文件,如下所示: # test_cy.pyx from utils import say_hello cdef

我是Cython的新手,只是想尝试一个简单的脚本。我无法从模块导入函数并在另一个文件中使用它,但是如果我在同一个文件中声明该函数,它就可以正常工作。这里可能有什么问题。我错过什么了吗

这是原始代码段(test_cy.pyx):

我可以像(编译后)那样运行它:

但是,如果我将say_hello函数移动到另一个文件(utils.pyx):

。。。并将其导入我的原始test_cy.pyx文件,如下所示:

# test_cy.pyx

from utils import say_hello

cdef char* fn(int n):
  cdef char* hello = say_hello()
  return hello

def test():
  cdef char* n = fn(1000)
  print(n)
由于出现以下错误,我无法将其编译:

>>> python3 setup.py build_ext --inplace
...
Error compiling Cython file:
------------------------------------------------------------
...
from utils import say_hello

cdef char* fn(int n):
  cdef char* hello = say_hello()
      ^
------------------------------------------------------------

test_cy.pyx:4:7: Storing unsafe C derivative of temporary Python reference
Traceback (most recent call last):
  File "setup.py", line 11, in <module>
    sources=["utils.pyx"]
  File "/Users/asim/.pyenv/versions/3.6.9/lib/python3.6/site-packages/Cython/Build/Dependencies.py", line 1101, in cythonize
    cythonize_one(*args)
  File "/Users/asim/.pyenv/versions/3.6.9/lib/python3.6/site-packages/Cython/Build/Dependencies.py", line 1224, in cythonize_one
    raise CompileError(None, pyx_file)
Cython.Compiler.Errors.CompileError: test_cy.pyx
请帮助我,像从另一个模块导入函数这样简单的事情应该不会这么复杂。我可能错过了一些琐碎的事情。谢谢

cpdef char* say_hello():
  message = json.dumps({"message": "Hello world"})
  return message.encode()
这是一场即将发生的灾难(尽管Cython似乎无法发出警告)。您的
char*
指向的数据由
message.encode()
的结果保存,这是一个临时Python对象,创建后立即销毁。因此,您的
char*
立即无效

用C语言思考这个问题:要返回
char*
必须有人拥有
char*
,您应该确切地知道该所有者是谁。 要返回
char*
而不承担分配/解除分配自己的责任,没有一种简单、合理的方法。除非您已经准备好这样做并了解如何做,否则我建议您从代码中删除所有
char*
,然后返回Python对象


您遇到的错误是因为Cython使用
cimport
了解Cython函数

from utils cimport say_hello

没有
cimport
它认为
say_hello
只是一个普通的Python函数,返回一个普通的Python对象。但是,即使进行了此更改,您的代码仍然无效-您刚刚将错误移到Cython看不到的地方。

非常感谢您的回答!我想问你一些问题,因为我对C不太熟悉。我的函数几乎总是返回char*(字节)。你能告诉我怎样做才是正确的方法吗?只要一些资源就好了。再次感谢您的回答!:)问题是Cython没有(也不能)保护您免受C语言的任何复杂性。因此,如果您不熟悉C,最好的方法是返回Python对象,而不是
char*
。如果您真的想使用
char*
,那么您应该使用
malloc
分配它们,从Python字符串复制数据(可能是
strcpy
)并使用
free
释放它们,确保
释放
malloc
中的所有内容(仅此而已)。感谢您的指导!我会详细研究这个问题。
>>> python3 setup.py build_ext --inplace
...
Error compiling Cython file:
------------------------------------------------------------
...
from utils import say_hello

cdef char* fn(int n):
  cdef char* hello = say_hello()
      ^
------------------------------------------------------------

test_cy.pyx:4:7: Storing unsafe C derivative of temporary Python reference
Traceback (most recent call last):
  File "setup.py", line 11, in <module>
    sources=["utils.pyx"]
  File "/Users/asim/.pyenv/versions/3.6.9/lib/python3.6/site-packages/Cython/Build/Dependencies.py", line 1101, in cythonize
    cythonize_one(*args)
  File "/Users/asim/.pyenv/versions/3.6.9/lib/python3.6/site-packages/Cython/Build/Dependencies.py", line 1224, in cythonize_one
    raise CompileError(None, pyx_file)
Cython.Compiler.Errors.CompileError: test_cy.pyx
from distutils.core import setup
from distutils.extension import Extension
from Cython.Build import cythonize

setup(
  ext_modules = cythonize([
    Extension("test_cy",
              sources=["test_cy.pyx"]
    ),
    Extension("utils",
              sources=["utils.pyx"]
    )
  ])
)
cpdef char* say_hello():
  message = json.dumps({"message": "Hello world"})
  return message.encode()
from utils cimport say_hello