[pypy-svn] r76460 - in pypy/branch/reflex-support/pypy/module/cppyy: . include src test

wlav at codespeak.net wlav at codespeak.net
Tue Aug 3 23:22:06 CEST 2010


Author: wlav
Date: Tue Aug  3 23:22:05 2010
New Revision: 76460

Modified:
   pypy/branch/reflex-support/pypy/module/cppyy/capi.py
   pypy/branch/reflex-support/pypy/module/cppyy/converter.py
   pypy/branch/reflex-support/pypy/module/cppyy/helper.py
   pypy/branch/reflex-support/pypy/module/cppyy/include/reflexcwrapper.h
   pypy/branch/reflex-support/pypy/module/cppyy/interp_cppyy.py
   pypy/branch/reflex-support/pypy/module/cppyy/pythonify.py
   pypy/branch/reflex-support/pypy/module/cppyy/src/reflexcwrapper.cxx
   pypy/branch/reflex-support/pypy/module/cppyy/test/test_cppyy.py
   pypy/branch/reflex-support/pypy/module/cppyy/test/test_datatypes.py
Log:
Support for public data members of type (unsigned) char and renaming various names for consistency.


Modified: pypy/branch/reflex-support/pypy/module/cppyy/capi.py
==============================================================================
--- pypy/branch/reflex-support/pypy/module/cppyy/capi.py	(original)
+++ pypy/branch/reflex-support/pypy/module/cppyy/capi.py	Tue Aug  3 23:22:05 2010
@@ -85,19 +85,36 @@
     "cppyy_method_name",
     [C_TYPEHANDLE, rffi.INT], rffi.CCHARP,
     compilation_info=eci)
-c_result_type_method = rffi.llexternal(
-    "cppyy_result_type_method",
+c_method_result_type = rffi.llexternal(
+    "cppyy_method_result_type",
     [C_TYPEHANDLE, rffi.INT], rffi.CCHARP,
     compilation_info=eci)
-c_num_args_method = rffi.llexternal(
-    "cppyy_num_args_method",
+c_method_num_args = rffi.llexternal(
+    "cppyy_method_num_args",
     [C_TYPEHANDLE, rffi.INT], rffi.INT,
     compilation_info=eci)
-c_arg_type_method = rffi.llexternal(
-    "cppyy_arg_type_method",
+c_method_arg_type = rffi.llexternal(
+    "cppyy_method_arg_type",
     [C_TYPEHANDLE, rffi.INT, rffi.INT], rffi.CCHARP,
     compilation_info=eci)
 
+c_num_data_members = rffi.llexternal(
+    "cppyy_num_data_members",
+    [C_TYPEHANDLE], rffi.INT,
+    compilation_info=eci)
+c_data_member_name = rffi.llexternal(
+    "cppyy_data_member_name",
+    [C_TYPEHANDLE, rffi.INT], rffi.CCHARP,
+    compilation_info=eci)
+c_data_member_type = rffi.llexternal(
+    "cppyy_data_member_type",
+    [C_TYPEHANDLE, rffi.INT], rffi.CCHARP,
+    compilation_info=eci)
+c_data_member_offset = rffi.llexternal(
+    "cppyy_data_member_offset",
+    [C_TYPEHANDLE, rffi.INT], rffi.INT,
+    compilation_info=eci)
+
 c_is_constructor = rffi.llexternal(
     "cppyy_is_constructor",
     [C_TYPEHANDLE, rffi.INT], rffi.INT,

Modified: pypy/branch/reflex-support/pypy/module/cppyy/converter.py
==============================================================================
--- pypy/branch/reflex-support/pypy/module/cppyy/converter.py	(original)
+++ pypy/branch/reflex-support/pypy/module/cppyy/converter.py	Tue Aug  3 23:22:05 2010
@@ -10,6 +10,9 @@
     def convert_argument(self, space, w_obj):
         raise NotImplementedError("abstract base class")
 
+    def from_memory(self, space, w_obj, offset):
+        raise NotImplementedError("abstract base class")
+
     def free_argument(self, arg):
         lltype.free(arg, flavor='raw')
 
@@ -41,6 +44,17 @@
         x = rffi.str2charp(arg)
         return rffi.cast(rffi.VOIDP, x)
 
+    def from_memory(self, space, w_obj, offset):
+        obj = space.interpclass_w(space.findattr(w_obj, space.wrap("_cppinstance")))
+        fieldptr = lltype.direct_ptradd(obj.rawobject, offset)
+        return space.wrap(fieldptr[0])
+
+    def to_memory(self, space, w_obj, w_value, offset):
+        obj = space.interpclass_w(space.findattr(w_obj, space.wrap("_cppinstance")))
+        fieldptr = lltype.direct_ptradd(obj.rawobject, offset)
+        print w_value
+        fieldptr[0] = space.str_w(w_value)
+
 class IntConverter(TypeConverter):
     def convert_argument(self, space, w_obj):
         arg = space.c_int_w(w_obj)
@@ -87,6 +101,7 @@
                              space.wrap("cannot pass %s as %s" % (
                                  space.type(w_obj).getname(space, "?"),
                                  self.cpptype.name)))
+
     def free_argument(self, arg):
         pass
         

Modified: pypy/branch/reflex-support/pypy/module/cppyy/helper.py
==============================================================================
--- pypy/branch/reflex-support/pypy/module/cppyy/helper.py	(original)
+++ pypy/branch/reflex-support/pypy/module/cppyy/helper.py	Tue Aug  3 23:22:05 2010
@@ -3,17 +3,25 @@
 def compound(name):
     name = "".join(rstring.split(name, "const")) # poor man's replace
     i = _find_qualifier_index(name)
+    if name[-1] == "]":                          # array type
+        return "*"
     return "".join(name[i:].split(" "))
 
 def _find_qualifier_index(name):
     i = len(name)
     for i in range(len(name) - 1, -1, -1):
         c = name[i]
-        if c.isalnum() or c == ">":
+        if c.isalnum() or c == ">" or c == "]":
             break
     return i + 1
 
 def clean_type(name):
     assert name.find("const") == -1
     i = _find_qualifier_index(name)
-    return name[:i].strip(' ')
+    name = name[:i].strip(' ')
+    if name[-1] == "]":
+        for i in range(len(name) - 1, -1, -1):
+            c = name[i]
+            if c == "[":
+                return name[:i]
+    return name

Modified: pypy/branch/reflex-support/pypy/module/cppyy/include/reflexcwrapper.h
==============================================================================
--- pypy/branch/reflex-support/pypy/module/cppyy/include/reflexcwrapper.h	(original)
+++ pypy/branch/reflex-support/pypy/module/cppyy/include/reflexcwrapper.h	Tue Aug  3 23:22:05 2010
@@ -14,6 +14,7 @@
     void* cppyy_allocate(cppyy_typehandle_t handle);
     void cppyy_deallocate(cppyy_typehandle_t handle, cppyy_object_t instance);
 
+    /* method/function dispatching */
     void   cppyy_call_v(cppyy_typehandle_t handle, int method_index, cppyy_object_t self, int numargs, void* args[]);
     int    cppyy_call_b(cppyy_typehandle_t handle, int method_index, cppyy_object_t self, int numargs, void* args[]);
     char   cppyy_call_c(cppyy_typehandle_t handle, int method_index, cppyy_object_t self, int numargs, void* args[]);
@@ -24,11 +25,18 @@
     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);
 
+    /* method/function reflection information */
     int cppyy_num_methods(cppyy_typehandle_t handle);
     char* cppyy_method_name(cppyy_typehandle_t handle, int method_index);
-    char* cppyy_result_type_method(cppyy_typehandle_t handle, int method_index);
-    int cppyy_num_args_method(cppyy_typehandle_t handle, int method_index);
-    char* cppyy_arg_type_method(cppyy_typehandle_t handle, int method_index, int index);
+    char* cppyy_method_result_type(cppyy_typehandle_t handle, int method_index);
+    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);
+
+    /* 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);

Modified: pypy/branch/reflex-support/pypy/module/cppyy/interp_cppyy.py
==============================================================================
--- pypy/branch/reflex-support/pypy/module/cppyy/interp_cppyy.py	(original)
+++ pypy/branch/reflex-support/pypy/module/cppyy/interp_cppyy.py	Tue Aug  3 23:22:05 2010
@@ -35,7 +35,8 @@
     if handle:
         cpptype = W_CPPType(space, name, handle)
         state.cpptype_cache[name] = cpptype
-        cpptype._find_func_members()
+        cpptype._find_methods()
+        cpptype._find_data_members()
         return cpptype
 
     raise OperationError(space.w_TypeError, space.wrap("no such C++ class %s" % name))
@@ -213,6 +214,28 @@
 )
 
 
+class W_CPPDataMember(Wrappable):
+    _immutable_fields_ = ["converter", "offset"]
+
+    def __init__(self, space, cpptype, offset):
+        self.space = space
+        self.converter = converter.get_converter(self.space, cpptype)
+        self.offset = offset
+
+    def __get__(self, args_w):
+        return self.converter.from_memory(self.space, args_w[0], self.offset)
+
+    def __set__(self, args_w):
+        self.converter.to_memory(self.space, args_w[0], args_w[1], self.offset)
+        return None
+
+W_CPPDataMember.typedef = TypeDef(
+    'CPPDataMember',
+    __get__ = interp2app(W_CPPDataMember.__get__, unwrap_spec=['self', 'args_w']),
+    __set__ = interp2app(W_CPPDataMember.__set__, unwrap_spec=['self', 'args_w']),
+)
+
+
 class W_CPPType(Wrappable):
     _immutable_fields_ = ["name","handle"]
 
@@ -220,30 +243,33 @@
         self.space = space
         self.name = name
         self.handle = handle
-        self.function_members = {}
-        # Do not call "self._find_func_members()" here, so that a distinction can be
-        #  made between testing for existence (i.e. existence in the cache of classes)
-        #  and actual use. Point being that a class can use itself, e.g. as a return
-        #  type or an argument to one of its methods.
+        self.methods = {}
+        # Do not call "self._find_methods()" here, so that a distinction can
+        #  be made between testing for existence (i.e. existence in the cache
+        #  of classes) and actual use. Point being that a class can use itself,
+        #  e.g. as a return type or an argument to one of its methods.
+
+        self.data_members = {}
+        # Idem self.methods: a type could hold itself by pointer.
     
-    def _find_func_members(self):
-        num_func_members = capi.c_num_methods(self.handle)
+    def _find_methods(self):
+        num_methods = capi.c_num_methods(self.handle)
         args_temp = {}
-        for i in range(num_func_members):
-            func_member_name = capi.charp2str_free(capi.c_method_name(self.handle, i))
+        for i in range(num_methods):
+            method_name = capi.charp2str_free(capi.c_method_name(self.handle, i))
             cppfunction = self._make_cppfunction(i)
-            overload = args_temp.setdefault(func_member_name, [])
+            overload = args_temp.setdefault(method_name, [])
             overload.append(cppfunction)
         for name, functions in args_temp.iteritems():
             overload = W_CPPOverload(self.space, name, functions[:])
-            self.function_members[name] = overload
+            self.methods[name] = overload
 
     def _make_cppfunction(self, method_index):
-        result_type = capi.charp2str_free(capi.c_result_type_method(self.handle, method_index))
-        num_args = capi.c_num_args_method(self.handle, method_index)
+        result_type = capi.charp2str_free(capi.c_method_result_type(self.handle, method_index))
+        num_args = capi.c_method_num_args(self.handle, method_index)
         argtypes = []
         for i in range(num_args):
-            argtype = capi.charp2str_free(capi.c_arg_type_method(self.handle, method_index, i))
+            argtype = capi.charp2str_free(capi.c_method_arg_type(self.handle, method_index, i))
             argtypes.append(argtype)
         if capi.c_is_constructor(self.handle, method_index):
             cls = CPPConstructor
@@ -253,12 +279,28 @@
             cls = CPPMethod
         return cls(self, method_index, result_type, argtypes)
 
-    def get_function_members(self):
-        return self.space.newlist([self.space.wrap(name) for name in self.function_members])
+    def _find_data_members(self):
+        num_data_members = capi.c_num_data_members(self.handle)
+        for i in range(num_data_members):
+            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)
+            self.data_members[data_member_name] = data_member
+
+    def get_method_names(self):
+        return self.space.newlist([self.space.wrap(name) for name in self.methods])
 
     @jit.purefunction
     def get_overload(self, name):
-        return self.function_members[name]
+        return self.methods[name]
+
+    def get_data_member_names(self):
+        return self.space.newlist([self.space.wrap(name) for name in self.data_members])
+
+    @jit.purefunction
+    def get_data_member(self, name):
+        return self.data_members[name]
 
     def invoke(self, name, args_w):
         overload = self.get_overload(name)
@@ -270,8 +312,10 @@
 
 W_CPPType.typedef = TypeDef(
     'CPPType',
-    get_function_members = interp2app(W_CPPType.get_function_members, unwrap_spec=['self']),
+    get_method_names = interp2app(W_CPPType.get_method_names, unwrap_spec=['self']),
     get_overload = interp2app(W_CPPType.get_overload, unwrap_spec=['self', str]),
+    get_data_member_names = interp2app(W_CPPType.get_data_member_names, unwrap_spec=['self']),
+    get_data_member = interp2app(W_CPPType.get_data_member, unwrap_spec=['self', str]),
     invoke = interp2app(W_CPPType.invoke, unwrap_spec=['self', str, 'args_w']),
     construct = interp2app(W_CPPType.construct, unwrap_spec=['self', 'args_w']),
 )

Modified: pypy/branch/reflex-support/pypy/module/cppyy/pythonify.py
==============================================================================
--- pypy/branch/reflex-support/pypy/module/cppyy/pythonify.py	(original)
+++ pypy/branch/reflex-support/pypy/module/cppyy/pythonify.py	Tue Aug  3 23:22:05 2010
@@ -54,13 +54,16 @@
     # TODO: handle base classes
     cpptype = cppyy._type_byname(name)
     d = {"_cppyyclass" : cpptype}
-    for f in cpptype.get_function_members():
+    for f in cpptype.get_method_names():
         cppol = cpptype.get_overload(f)
         if cppol.is_static():
             d[f] = make_static_function(cpptype, f, cppol.get_returntype())
         else:
             d[f] = make_method(f, cppol.get_returntype())
 
+    for dm in cpptype.get_data_member_names():
+         d[dm] = cpptype.get_data_member(dm)
+
     pycpptype = CppyyClass(name, (CppyyObject,), d)
 
     return pycpptype
@@ -77,6 +80,7 @@
             self.__dict__[attr] = cppclass
             return cppclass
         except TypeError, e:
+            import traceback
             raise AttributeError("'gbl' object has no attribute '%s'" % attr)
 
 

Modified: pypy/branch/reflex-support/pypy/module/cppyy/src/reflexcwrapper.cxx
==============================================================================
--- pypy/branch/reflex-support/pypy/module/cppyy/src/reflexcwrapper.cxx	(original)
+++ pypy/branch/reflex-support/pypy/module/cppyy/src/reflexcwrapper.cxx	Tue Aug  3 23:22:05 2010
@@ -18,6 +18,7 @@
 }
 
 
+/* method/function dispatching -------------------------------------------- */
 void cppyy_call_v(cppyy_typehandle_t handle, int method_index,
                   cppyy_object_t self, int numargs, void* args[]) {
     std::vector<void*> arguments(args, args+numargs);
@@ -96,6 +97,7 @@
 }
 
 
+/* method/function reflection information --------------------------------- */
 int cppyy_num_methods(cppyy_typehandle_t handle) {
     Reflex::Type t((Reflex::TypeName*)handle);
     // for (int i = 0; i < (int)t.FunctionMemberSize(); i++) {
@@ -120,7 +122,7 @@
     return name_char;
 }
 
-char* cppyy_result_type_method(cppyy_typehandle_t handle, int method_index) {
+char* cppyy_method_result_type(cppyy_typehandle_t handle, int method_index) {
     Reflex::Type t((Reflex::TypeName*)handle);
     Reflex::Member m = t.FunctionMemberAt(method_index);
     Reflex::Type rt = m.TypeOf().ReturnType();
@@ -130,13 +132,13 @@
     return name_char;
 }
 
-int cppyy_num_args_method(cppyy_typehandle_t handle, int method_index) {
+int cppyy_method_num_args(cppyy_typehandle_t handle, int method_index) {
     Reflex::Type t((Reflex::TypeName*)handle);
     Reflex::Member m = t.FunctionMemberAt(method_index);
     return m.FunctionParameterSize();
 }
 
-char* cppyy_arg_type_method(cppyy_typehandle_t handle, int method_index, int arg_index) {
+char* cppyy_method_arg_type(cppyy_typehandle_t handle, int method_index, int arg_index) {
     Reflex::Type t((Reflex::TypeName*)handle);
     Reflex::Member m = t.FunctionMemberAt(method_index);
     Reflex::Type at = m.TypeOf().FunctionParameterAt(arg_index);
@@ -147,6 +149,37 @@
 }
 
 
+/* data member reflection information ------------------------------------- */
+int cppyy_num_data_members(cppyy_typehandle_t handle) {
+    Reflex::Type t((Reflex::TypeName*)handle);
+    return t.DataMemberSize();
+}
+
+char* cppyy_data_member_name(cppyy_typehandle_t handle, int data_member_index) {
+    Reflex::Type t((Reflex::TypeName*)handle);
+    Reflex::Member m = t.DataMemberAt(data_member_index);
+    std::string name = m.Name();
+    char* name_char = (char*)malloc(name.size() + 1);
+    strcpy(name_char, name.c_str());
+    return name_char;
+}
+
+char* cppyy_data_member_type(cppyy_typehandle_t handle, int data_member_index) {
+    Reflex::Type t((Reflex::TypeName*)handle);
+    Reflex::Member m = t.DataMemberAt(data_member_index);
+    std::string name = m.TypeOf().Name(Reflex::FINAL|Reflex::SCOPED|Reflex::QUALIFIED);
+    char* name_char = (char*)malloc(name.size() + 1);
+    strcpy(name_char, name.c_str());
+    return name_char;
+}
+
+size_t cppyy_data_member_offset(cppyy_typehandle_t handle, int data_member_index) {
+    Reflex::Type t((Reflex::TypeName*)handle);
+    Reflex::Member m = t.DataMemberAt(data_member_index);
+    return m.Offset();
+}
+
+
 int cppyy_is_constructor(cppyy_typehandle_t handle, int method_index) {
     Reflex::Type t((Reflex::TypeName*)handle);
     Reflex::Member m = t.FunctionMemberAt(method_index);

Modified: pypy/branch/reflex-support/pypy/module/cppyy/test/test_cppyy.py
==============================================================================
--- pypy/branch/reflex-support/pypy/module/cppyy/test/test_cppyy.py	(original)
+++ pypy/branch/reflex-support/pypy/module/cppyy/test/test_cppyy.py	Tue Aug  3 23:22:05 2010
@@ -21,7 +21,7 @@
         w_cppyyclass = interp_cppyy.type_byname(space, "example01")
         w_cppyyclass2 = interp_cppyy.type_byname(space, "example01")
         assert space.is_w(w_cppyyclass, w_cppyyclass2)
-        adddouble = w_cppyyclass.function_members["staticAddToDouble"]
+        adddouble = w_cppyyclass.methods["staticAddToDouble"]
         func, = adddouble.functions
         assert isinstance(func.executor, executor.DoubleExecutor)
         assert func.arg_types == ["double"]

Modified: pypy/branch/reflex-support/pypy/module/cppyy/test/test_datatypes.py
==============================================================================
--- pypy/branch/reflex-support/pypy/module/cppyy/test/test_datatypes.py	(original)
+++ pypy/branch/reflex-support/pypy/module/cppyy/test/test_datatypes.py	Tue Aug  3 23:22:05 2010
@@ -53,19 +53,19 @@
         """
         raises(TypeError, 'c.set_bool(10)')
 
+        # char types through functions
         c.set_char('c');   assert c.get_char()  == 'c'
         c.set_uchar('e');  assert c.get_uchar() == 'e'
-        """
-        # char types
+
+        # char types through data members
         c.m_char = 'b';    assert c.get_char()  ==     'b'
-        c.m_char = 40;     assert c.get_char()  == chr(40)
+        #c.m_char = 40;     assert c.get_char()  == chr(40)
         c.set_char('c');   assert c.m_char      ==     'c'
-        c.set_char(41);    assert c.m_char      == chr(41)
+        #c.set_char(41);    assert c.m_char      == chr(41)
         c.m_uchar = 'd';   assert c.get_uchar() ==     'd'
-        c.m_uchar = 42;    assert c.get_uchar() == chr(42)
+        #c.m_uchar = 42;    assert c.get_uchar() == chr(42)
         c.set_uchar('e');  assert c.m_uchar     ==     'e'
-        c.set_uchar(43);   assert c.m_uchar     == chr(43)
-        """
+        #c.set_uchar(43);   assert c.m_uchar     == chr(43)
 
         raises(TypeError, 'c.set_char("string")')
 #        raises(TypeError, 'c.set_uchar(-1)')



More information about the Pypy-commit mailing list