如何从 cython 公开静态 constexpr

Posted

技术标签:

【中文标题】如何从 cython 公开静态 constexpr【英文标题】:How to expose static constexpr from cython 【发布时间】:2017-10-26 19:48:16 【问题描述】:

我需要将以下演示示例从 cpp 包装到 cython 以便在 Python 中使用

class Foo1 : public MFoo<unsigned int>  
public:
    constexpr Foo1(unsigned int val) : MFooval 
    
;

class Foo
public:
    static constexpr Foo1 any 0;
    static constexpr Foo1 one 1<<1;
    static constexpr Foo1 two 1<<2;
;

这是我目前拥有的 文件.pxd

cdef extern from "../MFoo.hpp":
    cdef cppclass MFoo:
        pass

cdef extern from "../header.hpp":
    cdef cppclass Foo1(MFoo):
        pass

cdef extern from "../header.hpp":
    cdef cppclass Foo:
        ###@staticmethod
        Foo1 _any "Foo::any"
        Foo1 _one "Foo::one"
        Foo1 _two "Foo::two"
###any=_any
### I also need to link my cpp definitions of any,one and two 
###to cython file but I am facing Error:Python object cannot be declared extern

我的文件.pyx

def Bar(self,PyFoo1 abc)
    return file.Bar(######) # how would I call something like Foo::one       

我需要知道如何将其包装在 cython 中。我正在使用How to expose a constexpr to Cython? 这很相似,但仍然不是很有用

【问题讨论】:

我认为问题在于使用静态成员变量,而不是constexpr。不过,您绝对不能将 staticmethod 装饰器应用于它们。 【参考方案1】:

您的主要问题是 Cython 没有提供表达 C++ 静态成员变量的方法。为了解决这个问题,您可以将它们放在全局范围内并使用字符串来确保生成正确的 C++ 代码。 constexpr 无关紧要 - Cython 不需要知道它。

我创建了一个从您的示例稍微简化的最小示例(例如,它省略了您未提供定义的不相关模板类):

class C 
public:
    constexpr C(unsigned int) 
;

class D 
public:
    static constexpr C any 0;
    static constexpr C one 1<<1;
    static constexpr C two 1<<2;
;

inline void bar(const C&) 

在 cython 中:

cdef extern from "whatever.hpp":
    cdef cppclass C:
        pass
    cdef cppclass D:
        pass
    C any "D::any"
    C one "D::one"
    C two "D::two"

    void bar(const C&)

请注意,我没有将 anyonetwo 放在 D 中,但要确保字符串创建 C++ 代码 D::any 等。


我认为还有第二个问题是关于如何从 Python 调用 bar。显然有很多选项,但一种简单的方法是传递一个字符串,并有一个 Cython 函数将字符串与 C++ 值匹配:

# except NULL allows Cython to signal an error to the calling function
cdef const C* get_C_instance(s) except NULL:
    if s=="any":
        return &any
    elif s=="one":
        return &one
    elif s=="two":
        return &two
    raise ValueError("Unrecognised string 0".format(s))

def py_bar(s):
    return bar(get_C_instance(s)[0])

这不是创建 Python 接口的唯一解决方案 - 例如,您可以创建一个包含 C 的包装类,并为其实例命名为 anyonetwo

【讨论】:

以上是关于如何从 cython 公开静态 constexpr的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 cython 将 python 类公开给 c++

Cython:不公开部分实现

如何最好地将 C++/Cython 项目编译成可执行文件?

使用 Cython 向另一个应用程序公开功能

如何在 Cython 中返回新的 C++ 对象?

如何初始化std :: vector的静态constexpr成员 在c ++ 11中?