我想为一个简单的 python 装饰器创建一个 c 函数(cdef public)。例如:
cdef public object WrapCPythonPyFunctionObject(int wrapper_id, object func):
def wrapper(*args, **kwargs):
print("enter wrapper")
result = func(*args, **kwargs)
print("exit wrapper")
return result
return <object>wrapper
输入
object func
和输出 object
都与我的 C/Python API 代码交互,并且预计为 PyFunctionObject * 类型。据我所知,这应该可行,但是当我尝试时,它在 cython 代码中的某个地方出现了段错误。这样的事情可能吗?我能找到的最接近此操作的是cython 的类型转换功能,但我不确定这是否符合我的要求。
提前致谢!
只需多填写评论中讨论的内容即可:
听起来问题可能在于从此函数返回的值被传递给需要
PyFunctionObject
的对象(Python 使用它来表示 Python 中定义的函数)。但是 Cython 函数是用 C 实现的,因此是 Cython 自己的 CyFunction
或 PyCFunctionObject
(取决于确切的编译器指令)。
假设情况确实如此,并且需要
PyFunctionObject
是一项硬性要求,那么可以在 Cython 中使用 eval
或 exec
来调用 Python 解释器并生成真正的 PyFunctionObject
:
cdef public object WrapCPythonPyFunctionObject(int wrapper_id, object func):
locals_dict = {'func', func}
exec("""
def wrapper(*args, **kwargs):
print("enter wrapper")
result = func(*args, **kwargs)
print("exit wrapper")
return result
""", {}, locals_dict)
return locals_dict['wrapper']
如果您想在包装器中使用 Cython 语言功能,这不太好。在这种情况下,您可以在 Cython 中定义
wrapper
,然后在其周围编写一个更薄的包装器:
cdef public object WrapCPythonPyFunctionObject(int wrapper_id, object func):
def wrapper(*args, **kwargs):
print("enter wrapper")
result = func(*args, **kwargs)
print("exit wrapper")
return result
return eval("lambda *args, **kwds: wrapper(*args, **kwds)")
我可能仍然不理解这里的最终目标,所以也许这没有帮助。但希望是这样。