Re: class with nested enum - reference in vector template

286 views
Skip to first unread message

Justin Israel

unread,
Mar 21, 2013, 9:29:08 PM3/21/13
to cython...@googlegroups.com
In the intest of full disclosure, I have just cross-posted on StackOverflow. If someone answers my problem there, I will be sure to close up this question here.


On Wednesday, March 20, 2013 11:55:16 PM UTC+13, Justin Israel wrote:
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 JobState::type enum. The closest I got to was after finding another similar post. Ended up with this:

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’

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? 

 
    

Justin Israel

unread,
Mar 22, 2013, 5:15:09 AM3/22/13
to cython...@googlegroups.com
I finally figured it out, though I am sure someone will point out some ways to improve my solution:

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)

Justin Israel

unread,
Mar 23, 2013, 5:13:56 PM3/23/13
to cython...@googlegroups.com
It was definitely non-trivial for me, as a cython beginner as well. Took a lot of google searching and trying combinations. If I had found something outlining this exact situation on the wiki it would have saved me a couple days. 

I am really interested to hear whether this is even the correct approach.


On Mar 22, 2013, at 11:23 PM, Björn Dahlgren wrote:

Nice job!

It would be great if this could (after review) either go into the wiki or documentation (or the 'Demos' dir).
It is non-trivial for new users (such as me) to know how to go about implementing these things and
hence the value of documenting these things can hardly be underestimated (if cython is to grow its userbase).

Best regards,
/Björn
--
 
---
You received this message because you are subscribed to a topic in the Google Groups "cython-users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/cython-users/71CMYN03kVc/unsubscribe?hl=en.
To unsubscribe from this group and all its topics, send an email to cython-users...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Robert Bradshaw

unread,
Mar 26, 2013, 2:45:11 AM3/26/13
to cython...@googlegroups.com
This is a valid solution, though I'm not sure why your original
approach didn't work (not enough of an example to go on there).
> You received this message because you are subscribed to the Google Groups
> "cython-users" group.
> To unsubscribe from this group and stop receiving emails from it, send an

Justin Israel

unread,
Mar 26, 2013, 3:43:19 AM3/26/13
to cython...@googlegroups.com
I think maybe the original attempt would have eventually worked had I realized I wasn't casting it properly to a python type. I ended up pretty much doing the same thing, with prefixing the enums instead of putting them in the struct.
Reply all
Reply to author
Forward
0 new messages