[pypy-svn] pypy reflex-support: read support for static (class-level) data members

wlav commits-noreply at bitbucket.org
Sat Feb 5 02:50:39 CET 2011


Author: Wim Lavrijsen <WLavrijsen at lbl.gov>
Branch: reflex-support
Changeset: r41622:ac289a3e9f8b
Date: 2011-02-04 17:50 -0800
http://bitbucket.org/pypy/pypy/changeset/ac289a3e9f8b/

Log:	read support for static (class-level) data members

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
@@ -31,7 +31,7 @@
         lib2 = cppyy.load_lib(self.shared_lib)
         assert self.datatypes is lib2
 
-    def test1ReadAccess( self ):
+    def test1InstanceDataReadAccess( self ):
         """Test read access to instance public data and verify values"""
 
         import cppyy, sys
@@ -105,7 +105,7 @@
 
         c.destruct()
 
-    def test2WriteAccess(self):
+    def test2InstanceDataWriteAccess(self):
         """Test write access to instance public data and verify values"""
 
         import cppyy, sys
@@ -187,7 +187,49 @@
 
         c.destruct()
 
-    def test3RangeAccess(self):
+    def test3ClassReadAccess(self):
+        """Test read access to class public data and verify values"""
+
+        import cppyy, sys
+        cppyy_test_data = cppyy.gbl.cppyy_test_data
+
+        c = cppyy_test_data()
+        assert isinstance(c, cppyy_test_data)
+
+        # char types
+        assert cppyy_test_data.s_char  == 's'
+        assert c.s_char                == 's'
+        assert c.s_uchar               == 'u'
+        assert cppyy_test_data.s_uchar == 'u'
+
+        # integer types
+        assert cppyy_test_data.s_short  == -101
+        assert c.s_short                == -101
+        assert c.s_ushort               ==  255
+        assert cppyy_test_data.s_ushort ==  255
+        assert cppyy_test_data.s_int    == -202
+        assert c.s_int                  == -202
+        assert c.s_uint                 ==  202
+        assert cppyy_test_data.s_uint   ==  202
+        assert cppyy_test_data.s_long   == -303
+        assert c.s_long                 == -303
+        assert c.s_ulong                ==  303
+        assert cppyy_test_data.s_ulong  ==  303
+
+        # floating point types
+        assert round(cppyy_test_data.s_float  + 404., 5) == 0
+        assert round(c.s_float                + 404., 5) == 0
+        assert round(cppyy_test_data.s_double + 505., 8) == 0
+        assert round(c.s_double               + 505., 8) == 0
+
+        c.destruct()
+
+    def test4ClassDataWriteAccess(self):
+        """Test write access to class public data and verify values"""
+
+        pass
+
+    def test5RangeAccess(self):
         """Test the ranges of integer types"""
 
         import cppyy, sys
@@ -201,7 +243,7 @@
 
         c.destruct()
 
-    def test4TypeConversions(self):
+    def test6TypeConversions(self):
         """Test conversions between builtin types"""
 
         import cppyy, sys
@@ -210,7 +252,6 @@
         c = cppyy_test_data()
         assert isinstance(c, cppyy_test_data)
 
-
         c.m_double = -1
         assert round(c.m_double + 1.0, 8) == 0
 

diff --git a/pypy/module/cppyy/include/reflexcwrapper.h b/pypy/module/cppyy/include/reflexcwrapper.h
--- a/pypy/module/cppyy/include/reflexcwrapper.h
+++ b/pypy/module/cppyy/include/reflexcwrapper.h
@@ -26,6 +26,9 @@
     void cppyy_destruct(cppyy_typehandle_t handle, cppyy_object_t self);
     cppyy_methptrgetter_t cppyy_get_methptr_getter(cppyy_typehandle_t handle, int method_index);
 
+    /* type properties */
+    int cppyy_is_subtype(cppyy_typehandle_t h1, cppyy_typehandle_t h2);
+
     /* method/function reflection information */
     int cppyy_num_methods(cppyy_typehandle_t handle);
     char* cppyy_method_name(cppyy_typehandle_t handle, int method_index);
@@ -33,16 +36,20 @@
     int cppyy_method_num_args(cppyy_typehandle_t handle, int method_index);
     char* cppyy_method_arg_type(cppyy_typehandle_t handle, int method_index, int index);
 
+    /* method properties */
+    int cppyy_is_constructor(cppyy_typehandle_t handle, int method_index);
+    int cppyy_is_staticmethod(cppyy_typehandle_t handle, int method_index);
+
     /* data member reflection information */
     int cppyy_num_data_members(cppyy_typehandle_t handle);
     char* cppyy_data_member_name(cppyy_typehandle_t handle, int data_member_index);
     char* cppyy_data_member_type(cppyy_typehandle_t handle, int data_member_index);
     size_t cppyy_data_member_offset(cppyy_typehandle_t handle, int data_member_index);
 
-    int cppyy_is_constructor(cppyy_typehandle_t handle, int method_index);
-    int cppyy_is_static(cppyy_typehandle_t handle, int method_index);
-    int cppyy_is_subtype(cppyy_typehandle_t h1, cppyy_typehandle_t h2);
+    /* data member properties */
+    int cppyy_is_staticdata(cppyy_typehandle_t handle, int data_member_index);
 
+    /* misc helper */
     void cppyy_free(void* ptr);
 
 #ifdef __cplusplus

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
@@ -102,6 +102,16 @@
 }
 
 
+/* type/class reflection information -------------------------------------- */
+int cppyy_is_subtype(cppyy_typehandle_t h1, cppyy_typehandle_t h2) {
+    if (h1 == h2)
+        return 1;
+    Reflex::Type t1((Reflex::TypeName*)h1);
+    Reflex::Type t2((Reflex::TypeName*)h2);
+    return (int)t2.HasBase(t1);
+}
+
+
 /* method/function reflection information --------------------------------- */
 int cppyy_num_methods(cppyy_typehandle_t handle) {
     Reflex::Type t((Reflex::TypeName*)handle);
@@ -154,6 +164,19 @@
 }
 
 
+int cppyy_is_constructor(cppyy_typehandle_t handle, int method_index) {
+    Reflex::Type t((Reflex::TypeName*)handle);
+    Reflex::Member m = t.FunctionMemberAt(method_index);
+    return m.IsConstructor();
+}
+
+int cppyy_is_staticmethod(cppyy_typehandle_t handle, int method_index) {
+    Reflex::Type t((Reflex::TypeName*)handle);
+    Reflex::Member m = t.FunctionMemberAt(method_index);
+    return m.IsStatic();
+}
+
+
 /* data member reflection information ------------------------------------- */
 int cppyy_num_data_members(cppyy_typehandle_t handle) {
     Reflex::Type t((Reflex::TypeName*)handle);
@@ -185,26 +208,14 @@
 }
 
 
-int cppyy_is_constructor(cppyy_typehandle_t handle, int method_index) {
+int cppyy_is_staticdata(cppyy_typehandle_t handle, int data_member_index) {
     Reflex::Type t((Reflex::TypeName*)handle);
-    Reflex::Member m = t.FunctionMemberAt(method_index);
-    return m.IsConstructor();
-}
-
-int cppyy_is_static(cppyy_typehandle_t handle, int method_index) {
-    Reflex::Type t((Reflex::TypeName*)handle);
-    Reflex::Member m = t.FunctionMemberAt(method_index);
+    Reflex::Member m = t.DataMemberAt(data_member_index);
     return m.IsStatic();
 }
 
-int cppyy_is_subtype(cppyy_typehandle_t h1, cppyy_typehandle_t h2) {
-    if (h1 == h2)
-        return 1;
-    Reflex::Type t1((Reflex::TypeName*)h1);
-    Reflex::Type t2((Reflex::TypeName*)h2);
-    return (int)t2.HasBase(t1);
-}
 
+/* misc helper ------------------------------------------------------------ */
 void cppyy_free(void* ptr) {
     free(ptr);
 }

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
@@ -261,6 +261,21 @@
 )
 
 
+class W_CPPStaticDataMember(W_CPPDataMember):
+    def __get__(self, args_w):
+        return self.converter.from_memory(self.space, self.space.w_None, self.offset)
+
+    def __set__(self, args_w):
+        self.converter.to_memory(self.space, self.space_w_None, args_w[1], self.offset)
+        return None
+
+W_CPPStaticDataMember.typedef = TypeDef(
+    'CPPStaticDataMember',
+    __get__ = interp2app(W_CPPStaticDataMember.__get__, unwrap_spec=['self', 'args_w']),
+    __set__ = interp2app(W_CPPStaticDataMember.__set__, unwrap_spec=['self', 'args_w']),
+)
+
+
 class W_CPPType(Wrappable):
     _immutable_fields_ = ["name", "handle"]
     def __init__(self, space, name, handle):
@@ -297,7 +312,7 @@
             argtypes.append(argtype)
         if capi.c_is_constructor(self.handle, method_index):
             cls = CPPConstructor
-        elif capi.c_is_static(self.handle, method_index):
+        elif capi.c_is_staticmethod(self.handle, method_index):
             cls = CPPFunction
         else:
             cls = CPPMethod
@@ -309,7 +324,10 @@
             data_member_name = capi.charp2str_free(capi.c_data_member_name(self.handle, i))
             cpptype = capi.charp2str_free(capi.c_data_member_type(self.handle, i))
             offset = capi.c_data_member_offset(self.handle, i)
-            data_member = W_CPPDataMember(self.space, cpptype, offset)
+            if capi.c_is_staticdata(self.handle, i):
+                data_member = W_CPPStaticDataMember(self.space, cpptype, offset)
+            else:
+                data_member = W_CPPDataMember(self.space, cpptype, offset)
             self.data_members[data_member_name] = data_member
 
     def get_method_names(self):

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
@@ -5,6 +5,8 @@
 from pypy.rlib.rarithmetic import r_singlefloat
 from pypy.rlib import jit, libffi
 
+from pypy.objspace.std.noneobject import W_NoneObject
+
 from pypy.module._rawffi.interp_rawffi import unpack_simple_shape
 from pypy.module._rawffi.array import W_Array
 
@@ -30,6 +32,13 @@
         rawobject = get_rawobject(space, w_obj)
         return lltype.direct_ptradd(rawobject, offset)
 
+    def _get_address(self, space, w_obj, offset):
+        if space.eq_w(w_obj, space.w_None): # meaning, static/global data
+            address = rffi.cast(rffi.CCHARP, offset)
+        else:
+            address = self._get_fieldptr(space, w_obj, offset)
+        return address
+
     def _is_abstract(self):
         raise NotImplementedError(
             "abstract base class" ) # more detailed part is not rpython: (actual: %s)" % type(self).__name__)
@@ -63,17 +72,16 @@
 
     def from_memory(self, space, w_obj, offset):
         # read access, so no copy needed
-        fieldptr = self._get_fieldptr(space, w_obj, offset)
-        ptrval = rffi.cast(rffi.UINT, fieldptr)
+        address = self._get_address(space, w_obj, offset)
         arr = space.interp_w(W_Array, unpack_simple_shape(space, space.wrap(self.typecode)))
-        return arr.fromaddress(space, fieldptr, self.size)
+        return arr.fromaddress(space, address, self.size)
 
     def to_memory(self, space, w_obj, w_value, offset):
         # copy the full array (uses byte copy for now)
-        fieldptr = self._get_fieldptr(space, w_obj, offset)
+        address = self._get_address(space, w_obj, offset)
         buf = space.interp_w(Buffer, w_value.getslotvalue(2))
         for i in range(min(self.size*self.typesize, buf.getlength())):
-            fieldptr[i] = buf.getitem(i)
+            address[i] = buf.getitem(i)
 
 
 class PtrTypeConverter(ArrayTypeConverter):
@@ -105,21 +113,21 @@
         return rffi.cast(rffi.VOIDP, x)
 
     def from_memory(self, space, w_obj, offset):
-        fieldptr = self._get_fieldptr(space, w_obj, offset)
-        if fieldptr[0] == '\x01':
+        address = self._get_address(space, w_obj, offset)
+        if address[0] == '\x01':
             return space.wrap(True)
         return space.wrap(False)
 
     def to_memory(self, space, w_obj, w_value, offset):
-        fieldptr = self._get_fieldptr(space, w_obj, offset)
+        address = self._get_address(space, w_obj, offset)
         arg = space.c_int_w(w_value)
         if arg != False and arg != True:
             raise OperationError(space.w_TypeError,
                                  space.wrap("boolean value should be bool, or integer 1 or 0"))
         if arg:
-           fieldptr[0] = '\x01'
+           address[0] = '\x01'
         else:
-           fieldptr[0] = '\x00'
+           address[0] = '\x00'
 
 class CharConverter(TypeConverter):
     libffitype = libffi.types.schar
@@ -147,12 +155,12 @@
         return rffi.cast(rffi.VOIDP, x)
 
     def from_memory(self, space, w_obj, offset):
-        fieldptr = self._get_fieldptr(space, w_obj, offset)
-        return space.wrap(fieldptr[0])
+        address = self._get_address(space, w_obj, offset)
+        return space.wrap(address[0])
 
     def to_memory(self, space, w_obj, w_value, offset):
-        fieldptr = self._get_fieldptr(space, w_obj, offset)
-        fieldptr[0] = self._from_space(space, w_value)
+        address = self._get_address(space, w_obj, offset)
+        address[0] = self._from_space(space, w_value)
 
 class LongConverter(TypeConverter):
     libffitype = libffi.types.slong
@@ -171,13 +179,13 @@
         argchain.arg(self._unwrap_object(space, w_obj))
 
     def from_memory(self, space, w_obj, offset):
-        fieldptr = self._get_fieldptr(space, w_obj, offset)
-        longptr = rffi.cast(self.rffiptrtype, fieldptr)
+        address = self._get_address(space, w_obj, offset)
+        longptr = rffi.cast(self.rffiptrtype, address)
         return space.wrap(longptr[0])
 
     def to_memory(self, space, w_obj, w_value, offset):
-        fieldptr = self._get_fieldptr(space, w_obj, offset)
-        longptr = rffi.cast(self.rffiptrtype, fieldptr)
+        address = self._get_address(space, w_obj, offset)
+        longptr = rffi.cast(self.rffiptrtype, address)
         longptr[0] = self._unwrap_object(space, w_value)
 
 class UnsignedLongConverter(LongConverter):
@@ -191,13 +199,13 @@
     libffitype = libffi.types.sshort
 
     def from_memory(self, space, w_obj, offset):
-        fieldptr = self._get_fieldptr(space, w_obj, offset)
-        shortptr = rffi.cast(rffi.SHORTP, fieldptr)
+        address = self._get_address(space, w_obj, offset)
+        shortptr = rffi.cast(rffi.SHORTP, address)
         return space.wrap(shortptr[0])
 
     def to_memory(self, space, w_obj, w_value, offset):
-        fieldptr = self._get_fieldptr(space, w_obj, offset)
-        shortptr = rffi.cast(rffi.SHORTP, fieldptr)
+        address = self._get_address(space, w_obj, offset)
+        shortptr = rffi.cast(rffi.SHORTP, address)
         shortptr[0] = rffi.cast(rffi.SHORT, space.c_int_w(w_value))
 
 class FloatConverter(TypeConverter):
@@ -210,13 +218,13 @@
         return rffi.cast(rffi.VOIDP, x)
 
     def from_memory(self, space, w_obj, offset):
-        fieldptr = self._get_fieldptr(space, w_obj, offset)
-        floatptr = rffi.cast(rffi.FLOATP, fieldptr)
+        address = self._get_address(space, w_obj, offset)
+        floatptr = rffi.cast(rffi.FLOATP, address)
         return space.wrap(float(floatptr[0]))
 
     def to_memory(self, space, w_obj, w_value, offset):
-        fieldptr = self._get_fieldptr(space, w_obj, offset)
-        floatptr = rffi.cast(rffi.FLOATP, fieldptr)
+        address = self._get_address(space, w_obj, offset)
+        floatptr = rffi.cast(rffi.FLOATP, address)
         floatptr[0] = r_singlefloat(space.float_w(w_value))
 
 class DoubleConverter(TypeConverter):
@@ -234,13 +242,13 @@
         argchain.arg(self._unwrap_object(space, w_obj))
 
     def from_memory(self, space, w_obj, offset):
-        fieldptr = self._get_fieldptr(space, w_obj, offset)
-        doubleptr = rffi.cast(rffi.DOUBLEP, fieldptr)
+        address = self._get_address(space, w_obj, offset)
+        doubleptr = rffi.cast(rffi.DOUBLEP, address)
         return space.wrap(doubleptr[0])
 
     def to_memory(self, space, w_obj, w_value, offset):
-        fieldptr = self._get_fieldptr(space, w_obj, offset)
-        doubleptr = rffi.cast(rffi.DOUBLEP, fieldptr)
+        address = self._get_address(space, w_obj, offset)
+        doubleptr = rffi.cast(rffi.DOUBLEP, address)
         doubleptr[0] = space.float_w(w_value)
 
 

diff --git a/pypy/module/cppyy/capi.py b/pypy/module/cppyy/capi.py
--- a/pypy/module/cppyy/capi.py
+++ b/pypy/module/cppyy/capi.py
@@ -81,6 +81,11 @@
     [C_TYPEHANDLE, rffi.INT], C_METHPTRGETTER_PTR,
     compilation_info=eci)
 
+c_is_subtype = rffi.llexternal(
+    "cppyy_is_subtype",
+    [C_TYPEHANDLE, C_TYPEHANDLE], rffi.INT,
+    compilation_info=eci)
+
 c_num_methods = rffi.llexternal(
     "cppyy_num_methods",
     [C_TYPEHANDLE], rffi.INT,
@@ -102,6 +107,15 @@
     [C_TYPEHANDLE, rffi.INT, rffi.INT], rffi.CCHARP,
     compilation_info=eci)
 
+c_is_constructor = rffi.llexternal(
+    "cppyy_is_constructor",
+    [C_TYPEHANDLE, rffi.INT], rffi.INT,
+    compilation_info=eci)
+c_is_staticmethod = rffi.llexternal(
+    "cppyy_is_staticmethod",
+    [C_TYPEHANDLE, rffi.INT], rffi.INT,
+    compilation_info=eci)
+
 c_num_data_members = rffi.llexternal(
     "cppyy_num_data_members",
     [C_TYPEHANDLE], rffi.INT,
@@ -119,18 +133,10 @@
     [C_TYPEHANDLE, rffi.INT], rffi.INT,
     compilation_info=eci)
 
-c_is_constructor = rffi.llexternal(
-    "cppyy_is_constructor",
+c_is_staticdata = rffi.llexternal(
+    "cppyy_is_staticdata",
     [C_TYPEHANDLE, rffi.INT], rffi.INT,
     compilation_info=eci)
-c_is_static = rffi.llexternal(
-    "cppyy_is_static",
-    [C_TYPEHANDLE, rffi.INT], rffi.INT,
-    compilation_info=eci)
-c_is_subtype = rffi.llexternal(
-    "cppyy_is_subtype",
-    [C_TYPEHANDLE, C_TYPEHANDLE], rffi.INT,
-    compilation_info=eci)
 
 c_free = rffi.llexternal(
     "cppyy_free",


More information about the Pypy-commit mailing list