【问题标题】:wrapping struct with nested enum - reference in vector template用嵌套枚举包装结构 - 向量模板中的引用
【发布时间】:2013-03-22 01:27:28
【问题描述】:

这是一天半前的cross-post of a question I asked in the cython-user group,但还没有得到任何回复,所以我在更一般的论坛上试试运气

我一直在尝试各种方法来包装以下代码,但出现了不同程度的错误。大量搜索让我偶然发现了类似的问题以及一张出色的愿望单,但老实说,我不确定我是否走在正确的道路上。

plow_types.h:

namespace Plow {

    struct JobState {
      enum type {
        INITIALIZE = 0,
        RUNNING = 1,
        FINISHED = 2
      };
    };
    ...
    class JobFilterT {
     public:
      ...
      std::vector<JobState::type>  states;
      ...

所以我试图包装这个Plow::JobState::type 枚举。在找到另一个类似的帖子后,我得到的最接近的结果是这个尝试:

plow_types.pxd:

cdef extern from "rpc/plow_types.h" namespace "Plow":

    enum JobState_type "Plow::JobState::type":
        INITIALIZE "Plow::JobState::INITIALIZE"
        RUNNING "Plow::JobState::RUNNING"
        FINISHED "Plow::JobState::FINISHED"

    struct JobState:
        JobState_type type
    ...
    cdef cppclass JobFilterT:
        vector[JobState_type] states 

我得到一个错误:

src/plow.cpp: In function ‘std::vector<Plow::JobState::type, std::allocator<Plow::JobState::type> > __pyx_convert_vector_from_py_enum__Plow_3a__3a_JobState_3a__3a_type(PyObject*)’:
src/plow.cpp:6688: error: invalid conversion from ‘long int’ to ‘Plow::JobState::type’

要么/要么:

  1. 如何正确包装这个嵌套枚举?
  2. 是否有必要尝试完全包装它,或者我可以通过其他方式实现访问这些“命名空间”常量的目标吗?我是否应该完全忽略这些结构,并在我的 pyx 中定义我自己的常量版本,并使用匹配的 int 值?

我试图在我的 cython pyx 中简单地定义我自己的常量版本并将所有内容都视为 int (vector[int] states) 但编译器抱怨不知道如何进行从 int longPlow::JobState::type 的转换.

【问题讨论】:

  • 不使用命名空间有什么原因吗?
  • 在我包装的 C++ 中? c++ 代码位于 Plow 命名空间内。

标签: python c++ enums nested cython


【解决方案1】:

在尝试了令人难以置信的组合之后,我终于弄明白了。在问这个问题之前,离我的最后一次尝试不远了……

plow_types.pxd:

我需要忘记 JobState 结构,只包装枚举。但我还需要将它们映射到 cython 中的新名称,以避免使用类似的命名空间技术与其他枚举发生名称冲突。

cdef extern from "rpc/plow_types.h" namespace "Plow":

    ctypedef enum JobState_type "Plow::JobState::type":
        JOBSTATE_INITIALIZE "Plow::JobState::INITIALIZE"
        JOBSTATE_RUNNING "Plow::JobState::RUNNING"
        JOBSTATE_FINISHED "Plow::JobState::FINISHED" 

现在我可以在 vector[JobState_type] 之类的内容中引用 JobState_type。然后我使用这种方法以只读方式使我的常量在 python 中可用:

job.pyx:

cimport cython

@cython.internal
cdef class _JobState:
    cdef:
        readonly int INITIALIZE 
        readonly int RUNNING 
        readonly int FINISHED 

    def __cinit__(self):
        self.INITIALIZE = JOBSTATE_INITIALIZE
        self.RUNNING = JOBSTATE_RUNNING
        self.FINISHED = JOBSTATE_FINISHED

JobState = _JobState()

这给了我一个JobState 的公共实例,具有只读常量属性。

当需要从 python 值列表转换回 vector[JobState_type] 时,我会这样做:

someList = [JobState.RUNNING]
...
cdef:
    JobState_type i
    vector[JobState_type] vec_states

for i in someList:
    vec_states.push_back(i)

【讨论】:

  • 谢谢。通过单例类将枚举值公开为只读常量的好主意。
  • 这对我不起作用。当我做同样的事情时,我班级上的那些属性不再是整数。它们属于“getset_descriptor”类型。我不能将枚举传递给声明为采用该枚举的函数。它抱怨我没有给它一个int
  • @eric.frederich,这在我维护的两个不同代码库中继续为我工作。您是否有可用的要点,显示您是如何实现它的?此外,由于 Python 没有枚举类型,因此这种方法确实不会为您提供类型安全性。如您所见,它们只是简单地转换为 int 字段。如果您想要暴露给 Python 的类型安全枚举,那么您可能必须采用不同的方法,在这种方法中,您有一个类似于 .value() 方法的基类类型。然后为每个枚举子类化它。然后你可以接受基类作为一种类型。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-22
  • 1970-01-01
相关资源
最近更新 更多