【问题标题】:Is there a way to call a cdef class method that has non-pythonic arguments?有没有办法调用具有非 pythonic 参数的 cdef 类方法?
【发布时间】:2020-09-22 13:04:25
【问题描述】:

实际上,我正在清理一个具有许多全局范围的函数和变量的 cython 模块。我认为 cdef 类将是打包其中一些函数的好方法。但是当我尝试调用这些类的一些方法时遇到了一个问题。我将其归结为这两个显示我的问题的示例。代码的功能并不重要,我只是想演示一下我面临的问题。

cdef class Foo:
    def __init__(self):
        pass

    cdef int deref(self, int *bar):
        return bar[0]

cdef int bar = 5
foo = Foo()
foo.deref(&bar)

如果我运行这段代码,我会得到一个错误

无法将 'int *' 转换为 Python 对象

但如果我在全局范围内定义所有内容,它就可以正常工作:

cdef int deref(int *bar):
    return bar[0]
cdef int bar = 5
deref(&bar)

我的问题是:这种方式可以调用cdef方法吗?

我的想法是它会起作用,因为这一切都是在 cython 中完成的,但出于某种原因,cython 想要将指针转换为 python 对象,然后再转换回 cython 对象?总是这样吗?我认为 cdef 类是使用 cython 时使用的有效工具。

无论如何,我已经用尽了我自己解决这个问题的尝试,并且想在放弃 cdef 类并回到函数式编程之前在这里问一下。

【问题讨论】:

  • 没有foo。如果你使用Foo,它应该是Foo().deref(&bar),它可以工作。
  • 你是对的,我编辑了代码添加了一个foo = Foo() 我看到了问题,我需要定义 foo 像:cdef Foo foo = Foo() 否则它是一个 python 对象。如果您在帖子中回答,我会:检查:它:) @ead

标签: cython


【解决方案1】:

通常 Cython 会检测到变量的 cdef 类型,例如对于

def doit():
    cdef int bar = 5
    foo = Foo()
    return foo.deref(&bar)

Cython 会看到 foo 的类型为 cdef Foo 并将其视为此类(上述代码构建)。

全局变量并非如此:

foo = Foo()

这是一个隐含的def 变量,可以通过modulename.foo 访问(或设置)。这意味着,Cython 无法确定 foo 的类型为 Foo - 它可以设置为 intfloat 等等。

因此,Cython 必须假定 foo 是一个纯 Python 对象,其中包含一个名为 deref 的 (def-) 方法,该方法具有 Python 参数和一个指针 cannot be cast to a Python object automatically - 这会导致您观察到的错误.

foo 声明为

cdef Foo foo=Foo()

从纯python中隐藏变量,因此不再可能通过modulename.foo访问它并为其分配一些任意对象。因此,Cython 可以假设 foo 确实属于 Foo 类型,从而授予对 cdefFoo 的函数的访问权限。

【讨论】:

    【解决方案2】:

    foo 必须声明为 Foo 对象

    cdef Foo foo = Foo()
    

    那么一切都好

    【讨论】:

      猜你喜欢
      • 2021-01-16
      • 1970-01-01
      • 2013-04-01
      • 2011-05-20
      • 1970-01-01
      • 1970-01-01
      • 2018-05-16
      • 1970-01-01
      • 2010-12-24
      相关资源
      最近更新 更多