Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

wrapping struct with nested enum - reference in vector template

This is a cross-post of a question I asked in the cython-user group a day and a half ago, but have not yet gotten any replies, so I am trying my luck in a more general forum

I have been trying every which way to wrap this following code, with various degrees of errors. Plenty of searching had me stumbling upon similar questions and also an outstanding wishlist ticket, but honestly I am not sure if I am even on the right path.

plow_types.h:

namespace Plow {

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

So I am trying to wrap this Plow::JobState::type enum. The closest I got, after finding another similar post, was ending up with this attempt:

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 

And I get an error:

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’

Either/or:

  1. How can I properly wrap this nested enum?
  2. Is this even necessary to try and wrap this exactly, or can I accomplish my goal of accessing these "namespaced" constants by some other means? Should I just completely ignore these structs, and define my own versions of the constants in my pyx, with matching int values?

I've tried to simply just define my own versions of the constants in my cython pyx and treat everything as int (vector[int] states) but the compiler complains about not knowing how to do conversions from int long to Plow::JobState::type.

like image 229
jdi Avatar asked Mar 22 '13 01:03

jdi


1 Answers

I finally figured it out, after trying an unbelievable amount of combinations. It was not to far off from my last attempt before asking the question...

plow_types.pxd:

I needed to just forget about that JobState struct, and only wrap the enum. But I also needed to map them to new names in cython to avoid name collisions with other enums using that similar namespace technique.

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" 

Now I can refer to JobState_type in stuff like vector[JobState_type]. Then I used this approach to making my constants available in python, in a readonly way:

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()

This gives me a public instance of JobState, with readonly constant attributes.

And when needing to convert back from a list of python values to a vector[JobState_type], I would do this:

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

for i in someList:
    vec_states.push_back(i)
like image 83
jdi Avatar answered Oct 23 '22 06:10

jdi