[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