[pypy-commit] pypy reflex-support: initial support for enums

wlav noreply at buildbot.pypy.org
Mon Mar 5 09:27:51 CET 2012


Author: Wim Lavrijsen <WLavrijsen at lbl.gov>
Branch: reflex-support
Changeset: r53222:d7c1d359ba1c
Date: 2012-03-05 00:22 -0800
http://bitbucket.org/pypy/pypy/changeset/d7c1d359ba1c/

Log:	initial support for enums

diff --git a/pypy/module/cppyy/capi/__init__.py b/pypy/module/cppyy/capi/__init__.py
--- a/pypy/module/cppyy/capi/__init__.py
+++ b/pypy/module/cppyy/capi/__init__.py
@@ -135,6 +135,10 @@
     "cppyy_is_namespace",
     [C_SCOPE], rffi.INT,
     compilation_info=backend.eci)
+c_is_enum = rffi.llexternal(
+    "cppyy_is_enum",
+    [rffi.CCHARP], rffi.INT,
+    compilation_info=backend.eci)
 
 # type/class reflection information ------------------------------------------
 c_final_name = rffi.llexternal(
diff --git a/pypy/module/cppyy/converter.py b/pypy/module/cppyy/converter.py
--- a/pypy/module/cppyy/converter.py
+++ b/pypy/module/cppyy/converter.py
@@ -633,6 +633,8 @@
             return InstancePtrConverter(space, cpptype, clean_name)
         elif compound == "":
             return InstanceConverter(space, cpptype, clean_name)
+    elif capi.c_is_enum(clean_name):
+        return UnsignedIntConverter(space, default)
     
     #   6) void converter, which fails on use
     #
diff --git a/pypy/module/cppyy/executor.py b/pypy/module/cppyy/executor.py
--- a/pypy/module/cppyy/executor.py
+++ b/pypy/module/cppyy/executor.py
@@ -327,6 +327,8 @@
             return InstancePtrExecutor(space, clean_name, cpptype)
         elif compound == "":
             return InstanceExecutor(space, clean_name, cpptype)
+    elif capi.c_is_enum(clean_name):
+        return UnsignedIntExecutor(space, "", None)
 
     # 4) additional special cases
     # ... none for now
diff --git a/pypy/module/cppyy/include/capi.h b/pypy/module/cppyy/include/capi.h
--- a/pypy/module/cppyy/include/capi.h
+++ b/pypy/module/cppyy/include/capi.h
@@ -47,6 +47,7 @@
 
     /* scope reflection information ------------------------------------------- */
     int cppyy_is_namespace(cppyy_scope_t scope);
+    int cppyy_is_enum(const char* type_name);
 
     /* class reflection information ------------------------------------------- */
     char* cppyy_final_name(cppyy_type_t type);
diff --git a/pypy/module/cppyy/interp_cppyy.py b/pypy/module/cppyy/interp_cppyy.py
--- a/pypy/module/cppyy/interp_cppyy.py
+++ b/pypy/module/cppyy/interp_cppyy.py
@@ -432,7 +432,6 @@
     def is_namespace(self):
         return self.space.w_True
 
-
 W_CPPNamespace.typedef = TypeDef(
     'CPPNamespace',
     update = interp2app(W_CPPNamespace.update, unwrap_spec=['self']),
diff --git a/pypy/module/cppyy/src/reflexcwrapper.cxx b/pypy/module/cppyy/src/reflexcwrapper.cxx
--- a/pypy/module/cppyy/src/reflexcwrapper.cxx
+++ b/pypy/module/cppyy/src/reflexcwrapper.cxx
@@ -36,7 +36,7 @@
 static inline std::vector<void*> build_args(int nargs, void* args) {
     std::vector<void*> arguments;
     arguments.reserve(nargs);
-    for (int i=0; i < nargs; ++i) {
+    for (int i = 0; i < nargs; ++i) {
 	char tc = ((CPPYY_G__value*)args)[i].type;
         if (tc != 'a' && tc != 'o')
             arguments.push_back(&((CPPYY_G__value*)args)[i]);
@@ -50,6 +50,8 @@
 /* name to opaque C++ scope representation -------------------------------- */
 cppyy_scope_t cppyy_get_scope(const char* scope_name) {
     Reflex::Scope s = Reflex::Scope::ByName(scope_name);
+    if (s.IsEnum())     // pretend to be builtin by returning 0
+        return (cppyy_type_t)0;
     return (cppyy_type_t)s.Id();
 }
 
@@ -184,10 +186,17 @@
     return s.IsNamespace();
 }
 
+int cppyy_is_enum(const char* type_name) {
+    Reflex::Type t = Reflex::Type::ByName(type_name);
+    return t.IsEnum();
+}
+
 
 /* class reflection information ------------------------------------------- */
 char* cppyy_final_name(cppyy_type_t handle) {
     Reflex::Scope s = scope_from_handle(handle);
+    if (s.IsEnum())
+        return cppstring_to_cstring("unsigned int");
     std::string name = s.Name(Reflex::FINAL);
     return cppstring_to_cstring(name);
 }
@@ -338,6 +347,20 @@
 /* data member reflection information ------------------------------------- */
 int cppyy_num_data_members(cppyy_scope_t handle) {
     Reflex::Scope s = scope_from_handle(handle);
+    // fix enum representation by adding them to the containing scope as per C++
+    // TODO: this (relatively harmlessly) dupes data members when updating in the
+    //       case s is a namespace
+    for (int isub = 0; isub < (int)s.ScopeSize(); ++isub) {
+        Reflex::Scope sub = s.SubScopeAt(isub);
+        if (sub.IsEnum()) {
+            for (int idata = 0;  idata < (int)sub.DataMemberSize(); ++idata) {
+                Reflex::Member m = sub.DataMemberAt(idata);
+                s.AddDataMember(m.Name().c_str(), sub, 0,
+                                Reflex::PUBLIC|Reflex::STATIC|Reflex::ARTIFICIAL,
+                                (char*)m.Offset());
+            }
+        }
+    }
     return s.DataMemberSize();
 }
 
@@ -358,6 +381,8 @@
 size_t cppyy_data_member_offset(cppyy_scope_t handle, int data_member_index) {
     Reflex::Scope s = scope_from_handle(handle);
     Reflex::Member m = s.DataMemberAt(data_member_index);
+    if (m.IsArtificial() && m.TypeOf().IsEnum())
+        return (size_t)&m.InterpreterOffset();
     return m.Offset();
 }
 
diff --git a/pypy/module/cppyy/test/datatypes.cxx b/pypy/module/cppyy/test/datatypes.cxx
--- a/pypy/module/cppyy/test/datatypes.cxx
+++ b/pypy/module/cppyy/test/datatypes.cxx
@@ -15,6 +15,7 @@
     m_ulong  =  33ul;
     m_float  = -44.f;
     m_double = -55.;
+    m_enum   = kNothing;
 
     m_short_array2  = new short[N];
     m_ushort_array2 = new unsigned short[N];
@@ -85,6 +86,7 @@
 unsigned long  cppyy_test_data::get_ulong()  { return m_ulong; }
 float          cppyy_test_data::get_float()  { return m_float; }
 double         cppyy_test_data::get_double() { return m_double; }
+cppyy_test_data::what cppyy_test_data::get_enum() { return m_enum; }
 
 short*          cppyy_test_data::get_short_array()   { return m_short_array; }
 short*          cppyy_test_data::get_short_array2()  { return m_short_array2; }
@@ -116,6 +118,7 @@
 void cppyy_test_data::set_ulong(unsigned long ul)   { m_ulong  = ul; }
 void cppyy_test_data::set_float(float f)            { m_float  = f; }
 void cppyy_test_data::set_double(double d)          { m_double = d; }
+void cppyy_test_data::set_enum(what w)              { m_enum   = w; }
 
 char           cppyy_test_data::s_char   = 's';
 unsigned char  cppyy_test_data::s_uchar  = 'u';
@@ -127,6 +130,7 @@
 unsigned long  cppyy_test_data::s_ulong  =  303ul;
 float          cppyy_test_data::s_float  = -404.f;
 double         cppyy_test_data::s_double = -505.;
+cppyy_test_data::what  cppyy_test_data::s_enum = cppyy_test_data::kNothing;
 
 
 //= global functions ========================================================
diff --git a/pypy/module/cppyy/test/datatypes.h b/pypy/module/cppyy/test/datatypes.h
--- a/pypy/module/cppyy/test/datatypes.h
+++ b/pypy/module/cppyy/test/datatypes.h
@@ -14,6 +14,9 @@
     cppyy_test_data();
     ~cppyy_test_data();
 
+// special cases
+   enum what { kNothing=6, kSomething=111, kLots=42 };
+
 // helper
     void destroy_arrays();
 
@@ -29,6 +32,7 @@
     unsigned long  get_ulong();
     float          get_float();
     double         get_double();
+    what           get_enum();
 
     short*          get_short_array();
     short*          get_short_array2();
@@ -60,6 +64,7 @@
     void set_ulong(unsigned long ul);
     void set_float(float f);
     void set_double(double d);
+    void set_enum(what w);
 
 public:
 // basic types
@@ -74,6 +79,7 @@
     unsigned long  m_ulong;
     float          m_float;
     double         m_double;
+    what           m_enum;
 
 // array types
     short           m_short_array[N];
@@ -108,6 +114,7 @@
     static unsigned long  s_ulong;
     static float          s_float;
     static double         s_double;
+    static what           s_enum;
 
 private:
     bool m_owns_arrays;
diff --git a/pypy/module/cppyy/test/test_datatypes.py b/pypy/module/cppyy/test/test_datatypes.py
--- a/pypy/module/cppyy/test/test_datatypes.py
+++ b/pypy/module/cppyy/test/test_datatypes.py
@@ -379,3 +379,40 @@
         assert gbl.is_global_pod(e)
         assert gbl.g_pod.m_int == 43
         assert gbl.g_pod.m_double == 2.14
+
+    def test11_enum(self):
+        """Test access to enums"""
+
+        import cppyy
+        gbl = cppyy.gbl
+
+        cppyy_test_data = cppyy.gbl.cppyy_test_data
+
+        c = cppyy_test_data()
+        assert isinstance(c, cppyy_test_data)
+
+        # TODO: test that the enum is accessible as a type
+
+        assert cppyy_test_data.kNothing   ==   6
+        assert cppyy_test_data.kSomething == 111
+        assert cppyy_test_data.kLots      ==  42
+
+        assert c.get_enum() == cppyy_test_data.kNothing
+        assert c.m_enum == cppyy_test_data.kNothing
+
+        c.m_enum = cppyy_test_data.kSomething
+        assert c.get_enum() == cppyy_test_data.kSomething
+        assert c.m_enum == cppyy_test_data.kSomething
+
+        c.set_enum(cppyy_test_data.kLots)
+        assert c.get_enum() == cppyy_test_data.kLots
+        assert c.m_enum == cppyy_test_data.kLots
+
+        assert c.s_enum == cppyy_test_data.s_enum
+        assert c.s_enum == cppyy_test_data.kNothing
+        assert cppyy_test_data.s_enum == cppyy_test_data.kNothing
+
+        c.s_enum = cppyy_test_data.kSomething
+        assert c.s_enum == cppyy_test_data.s_enum
+        assert c.s_enum == cppyy_test_data.kSomething
+        assert cppyy_test_data.s_enum == cppyy_test_data.kSomething


More information about the pypy-commit mailing list