使用 Cython 从标头导出常量

Posted

技术标签:

【中文标题】使用 Cython 从标头导出常量【英文标题】:Export constants from header with Cython 【发布时间】:2015-08-01 21:06:22 【问题描述】:

我正在使用 Cython 来包装 C 库。 C 库的头文件定义了许多常量,所以在我的 cython 模块中,我有类似的内容:

cdef extern from "lib.h":
    cdef int CONST_A = 0
    cdef int CONST_B = 1

当我编译扩展时,常量在 Python 中不可用。我尝试做这样的事情,但它似乎不起作用:

cdef extern from "lib.h":
    cdef int CONST_A = 0
    cdef int CONST_B = 1

CONST_A = CONST_A
CONST_B = CONST_B

关于如何使这些常量在 Python 中可用的任何想法?

【问题讨论】:

我认为您可以使用cpdef 而不是cdef 作为常量。 我试过了,还是不行。 github.com/cython/cython/commit/… 【参考方案1】:

你说得对,那里的 Cython 似乎有一个洞。

我可以声明cpdef int CONST_C = 3,它可以编译,但在 Python 中不可见。这似乎是一个错误——如果它接受语法,它应该对它做一些合理的事情。

似乎确实有效的一件事是:

cpdef enum:
    CONST_A = 0
    CONST_B = 1

这可能对您的情况足够好,也可能不够好,但它似乎适用于许多用例——也许这就是没有注意到该错误的原因?

【讨论】:

【参考方案2】:

我使用的解决方案很容易切换到“正确”的解决方案,一旦支持,就是在 .pyx 文件中以枚举名称为前缀重新声明枚举值,然后它们就很容易了发现。

所以在 foo.pxd 中:

cdef enum Mood:
    happy
    sad

然后在全局范围的 foo.pyx 中:

Mood_happy = happy
Mood_sad = sad

在 bar.py 中:

from foo import Mood_happy, Mood_sad

# do something with Mood_happy and Mood_sad as ints

【讨论】:

【参考方案3】:

评论太晚了,但是下面的代码怎么样? 这个想法来源于How can a #defined C value be exposed to Python in a Cython module?

此解决方案在我的库中运行良好。 “CONST_A”和“CONST_B”是 cdef/cpdef 函数的别名。 在 Cython(.pyx) 中,它们可以用作宏。 要将宏暴露给 Python,需要 CONST_A = _CONST_A 和 CONST_B = _CONST_B。

a.pyx

cdef extern from "lib.h":
    cdef int _CONST_A "CONST_A"
    cdef int _CONST_B "CONST_B"

def use_const():
    if CONST_A:
      do_something()
    if CONST_B:
      do_something()

CONST_A = _CONST_A
CONST_B = _CONST_B

编译后可以在python代码中使用。

使用_a.py

import a
print(a.CONST_A)
print(a.CONST_B)

【讨论】:

以上是关于使用 Cython 从标头导出常量的主要内容,如果未能解决你的问题,请参考以下文章

PyArray_Check 使用 Cython/C++ 给出分段错误

如何从 cython 公开静态 constexpr

Cython:从参考获得时,Numpy 数组缺少两个第一个元素

python怎么使用cython

ImportError:没有名为'Cython'的模块

从 C++ 函数 Cython 返回包含 PyObject 的复杂对象