[pypy-commit] pypy reflex-support: further STL support and initial class-specific pythonizations

wlav noreply at buildbot.pypy.org
Thu Jun 30 01:25:11 CEST 2011


Author: Wim Lavrijsen <WLavrijsen at lbl.gov>
Branch: reflex-support
Changeset: r45187:5a71dcc697ce
Date: 2011-06-27 17:32 -0700
http://bitbucket.org/pypy/pypy/changeset/5a71dcc697ce/

Log:	further STL support and initial class-specific pythonizations

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
@@ -77,13 +77,23 @@
     _immutable_ = True
     libffitype = libffi.types.slong
 
+    def _wrap_result(self, space, result):
+        return space.wrap(result)
+
     def execute(self, space, func, cppthis, num_args, args):
         result = capi.c_call_l(func.cpptype.handle, func.method_index, cppthis, num_args, args)
-        return space.wrap(result)
+        return self._wrap_result(space, result)
 
     def execute_libffi(self, space, libffifunc, argchain):
         return space.wrap(libffifunc.call(argchain, lltype.Signed))
 
+class ConstLongRefExecutor(LongExecutor):
+    _immutable_ = True
+
+    def _wrap_result(self, space, result):
+        longptr = rffi.cast(rffi.LONGP, result)
+        return space.wrap(longptr[0])
+
 class FloatExecutor(FunctionExecutor):
     _immutable_ = True
 
@@ -170,6 +180,7 @@
 
     #   2) drop '&': by-ref is pretty much the same as by-value, python-wise
     if compound and compound[len(compound)-1] == "&":
+        # TODO: this does not actually work with Reflex (?)
         try:
             return _executors[clean_name](space, "", None)
         except KeyError:
@@ -203,6 +214,8 @@
 _executors["unsigned short int*"] = ShortPtrExecutor
 _executors["int"]                 = LongExecutor
 _executors["int*"]                = LongPtrExecutor
+_executors["const int&"]          = ConstLongRefExecutor
+_executors["int&"]                = ConstLongRefExecutor
 _executors["unsigned int"]        = LongExecutor
 _executors["unsigned int*"]       = LongPtrExecutor
 _executors["long int"]            = LongExecutor
diff --git a/pypy/module/cppyy/helper.py b/pypy/module/cppyy/helper.py
--- a/pypy/module/cppyy/helper.py
+++ b/pypy/module/cppyy/helper.py
@@ -55,7 +55,7 @@
 #- operator mappings --------------------------------------------------------
 _operator_mappings = {}
 
-def map_operator_name(cppname, nargs):
+def map_operator_name(cppname, nargs, result_type):
     from pypy.module.cppyy import capi
 
     if cppname[0:8] == "operator":
@@ -72,6 +72,14 @@
         except KeyError:
             pass
 
+        # return-type dependent mapping
+        if op == "[]":
+            if result_type.find("const") != 0:
+                cpd = compound(result_type)
+                if cpd and cpd[len(cpd)-1] == "&":
+                    return "__setitem__"
+            return "__getitem__"
+
         # a couple more cases that depend on whether args were given
 
         if op == "*":   # dereference (not python) vs. multiplication
@@ -98,7 +106,7 @@
 # _operator_mappings["-"]   = "__sub__"          # id. (eq. __neg__)
 # _operator_mappings["*"]   = "__mul__"          # double meaning in C++
 
-_operator_mappings["[]"]  = "__getitem__"
+# _operator_mappings["[]"]  = "__getitem__"      # depends on return type
 _operator_mappings["()"]  = "__call__"
 _operator_mappings["/"]   = "__div__"            # __truediv__ in p3
 _operator_mappings["%"]   = "__mod__"
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
@@ -338,7 +338,8 @@
         for i in range(num_methods):
             method_name = capi.charp2str_free(capi.c_method_name(self.handle, i))
             pymethod_name = helper.map_operator_name(
-                method_name, capi.c_method_num_args(self.handle, i))
+                method_name, capi.c_method_num_args(self.handle, i),
+                capi.charp2str_free(capi.c_method_result_type(self.handle, i)))
             cppfunction = self._make_cppfunction(i)
             overload = args_temp.setdefault(pymethod_name, [])
             overload.append(cppfunction)
diff --git a/pypy/module/cppyy/pythonify.py b/pypy/module/cppyy/pythonify.py
--- a/pypy/module/cppyy/pythonify.py
+++ b/pypy/module/cppyy/pythonify.py
@@ -153,6 +153,7 @@
         if cppdm.is_static():
             setattr(metacpp, dm_name, cppdm)
 
+    _pythonize(pycpptype)
     return pycpptype
 
 def make_cpptemplatetype(template_name, scope):
@@ -195,6 +196,14 @@
 get_cppclass = get_cppitem         # TODO: restrict to classes only (?)
 
 
+def _pythonize(pyclass):
+
+    # map size -> __len__ (generally true for STL)
+    if hasattr(pyclass, 'size') and \
+            not hasattr(pyclass,'__len__') and callable(pyclass.size):
+        pyclass.__len__ = pyclass.size
+
+
 _loaded_shared_libs = {}
 def load_lib(name):
     try:
diff --git a/pypy/module/cppyy/test/test_stltypes.py b/pypy/module/cppyy/test/test_stltypes.py
--- a/pypy/module/cppyy/test/test_stltypes.py
+++ b/pypy/module/cppyy/test/test_stltypes.py
@@ -43,8 +43,9 @@
         for i in range(self.N):
             v.push_back(i)
             assert v.size() == i+1
-#           assert v[i] == i
+            assert v.at(i) == i
+            assert v[i] == i
 
         assert v.size() == self.N
-#       assert len(v) == self.N
+        assert len(v) == self.N
         v.destruct()


More information about the pypy-commit mailing list