在 Python C/C++ 扩展中实现装饰器,可以 wrap/decorate 在 Python 中运行

Implementing decorators in a Python C/C++ extension that can wrap/decorate functions in Python

Python 装饰器是解决很多问题的非常“pythonic”的解决方案。因此,我想在我的 C 扩展中包含一个预定义的装饰器,它可以装饰在包含我的扩展的 Python 文件中调用的函数。

我似乎无法在 CPython api 文档中找到任何描述如何编写装饰器的内容。任何 help/direction 将不胜感激。

具体来说,我希望 Python 代码如下所示:

import my_c_extension as m

@m.my_decorator(1)
def func():
    pass


func()

其中 my_decorator 会在调用 func 之前使用参数“1”执行一些功能(在 my_c_extension 中用 c 编写),并在调用 func 之后执行更多功能。

提前致谢!

对于此类问题,首先在 Python 中进行模拟通常会有所帮助。对于您的情况,我预计会有两个好处:

  • 如果您最终确实在扩展模块中完全实现装饰器,这将帮助您了解它应该如何工作以及您将创建的对象将保持什么状态。

  • 通常,您可以通过完成 Python 中的大部分工作来简化问题。

为了争论,假设您真正想做的是使用 C 扩展来帮助对低级 CPU 计数器进行采样以进行性能调整。这是一种通过 Python 和 C 的混合来实现这一点的方法。所有复杂的装饰器魔法都保留在 Python 中,而只有实际需要在 C 中的功能在 C 中。

def print_cpu_counter_info(counter_id):
    def wrapper(func):
        def wrapped(*args, **kwargs):
            before = my_c_extension.get_counter_value(counter_id)
            ret = func(*args, **kwargs)
            after = my_c_extension.get_counter_value(counter_id)
            print(f'counter {counter_id}: {before} -> {after}')
            return ret
        return wrapped
    return wrapper

@print_cpu_counter_info(L3_CACHE_LINE_MISS_COUNTER_ID)
def my_slow_func(...):
    ...

如果那不可行(太慢,比这更复杂,等等),那么您需要在 C 中创建扩展对象来复制 wrapperwrapped 的行为职能。这绝对是可行的,但需要一些工作,而且维护起来会更难。期望编写成百上千行 C 代码来复制上面示例中仅用几行 Python 代码的内容。