【问题标题】:Are "in place" Cython functions possible?“就地” Cython 功能是否可能?
【发布时间】:2021-10-15 04:25:43
【问题描述】:

假设我有一个返回 void 的 C 函数

void mysub_wrapper(int *a, int *b)
{
  *b = *a + 1;
}

我可以用 Cython 制作一个通过引用传递 ab 的包装器吗:

cdef extern void mysub_wrapper(int *a, int *b)

def mysub(int a, int b):
  mysub_wrapper(&a, &b)

这样就可以在python中调用了

a = 1
b = 0
mysub(a, b)

换句话说,我可以“就地”进行计算吗?

【问题讨论】:

  • Python 没有通过引用传递变量的概念。就地操作只能在可变容器上进行,例如列表和字典。

标签: python cython python-c-api cythonize


【解决方案1】:

你不能这样做。 cdef-ed 函数可以做到这一点(因为它只适用于 C 级别的类型,而不是 Python 类型),但 Python 级别的 ints 是不可变的(所以你不能实际上修改它们就地,您必须将它们重新绑定到一个新的int 对象),并且 Python 没有传递引用的概念(它是传递对象引用,大致翻译为传递指针的副本,不复制它指向的内容),所以当你调用 mysub(a, b) 时,它会生成引用 10 对象的别名,mysub 接收到的对象,但它失去了与 a 和 @987654330 的所有连接@函数外。

无论如何,这样做是非常不符合 Python 的。如果你必须这样做,just have the wrapper allocate its own C level int and pass a pointer to it to the underlying C function, then return the value after it's been reassigned to match Python behavior。性能成本是没有意义的(从 C int 重新包装到 Python int 是 Python 整体开销的巨大变化),并且返回新值而不是修改函数参数,即使可能,更干净,更少错误-prone 和 Pythonic 风格。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多