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

wlav at codespeak.net wlav at codespeak.net
Thu Jul 8 19:37:04 CEST 2010


Author: wlav
Date: Thu Jul  8 19:37:02 2010
New Revision: 76046

Added:
   pypy/branch/reflex-support/pypy/module/cppyy/helper.py   (contents, props changed)
   pypy/branch/reflex-support/pypy/module/cppyy/test/test_helper.py   (contents, props changed)
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/executor.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/src/reflexcwrapper.cxx
   pypy/branch/reflex-support/pypy/module/cppyy/test/test_cppyy.py
   pypy/branch/reflex-support/pypy/module/cppyy/test/test_pythonify.py
Log:
(wlav, cfbolz): work enough to be able to pass an instance as an argument.


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	Thu Jul  8 19:37:02 2010
@@ -91,6 +91,10 @@
     "is_static",
     [C_TYPEHANDLE, rffi.INT], rffi.INT,
     compilation_info=eci)
+c_is_subtype = rffi.llexternal(
+    "is_subtype",
+    [C_TYPEHANDLE, C_TYPEHANDLE], rffi.INT,
+    compilation_info=eci)
 c_dynamic_type = rffi.llexternal(
     "dynamic_type",
     [C_TYPEHANDLE, C_OBJECT], C_TYPEHANDLE,

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	Thu Jul  8 19:37:02 2010
@@ -1,5 +1,8 @@
+from pypy.interpreter.error import OperationError
 from pypy.rpython.lltypesystem import rffi, lltype
 
+from pypy.module.cppyy import helper, capi
+
 _converters = {}
 
 class TypeConverter(object):
@@ -30,13 +33,49 @@
         x = rffi.str2charp(arg)
         return rffi.cast(rffi.VOIDP, x)
 
-def get_converter(name):
+class InstancePtrConverter(TypeConverter):
+    _immutable_ = True
+    def __init__(self, space, cpptype):
+        self.cpptype = cpptype
+
+    def convert_argument(self, space, w_obj):
+        from pypy.module.cppyy import interp_cppyy
+        w_cppinstance = space.findattr(w_obj, space.wrap("_cppinstance"))
+        if w_cppinstance is not None:
+            w_obj = w_cppinstance
+        obj = space.interpclass_w(w_obj)
+        if isinstance(obj, interp_cppyy.W_CCPInstance):
+            if capi.c_is_subtype(obj.cppclass.handle, self.cpptype.handle):
+                return obj.rawobject
+        raise OperationError(space.w_TypeError,
+                             space.wrap("cannot pass %s as %s" % (
+                                 space.type(w_obj).getname(space, "?"),
+                                 self.cpptype.name)))
+    def free_argument(self, arg):
+        pass
+        
+
+def get_converter(space, name):
+    from pypy.module.cppyy import interp_cppyy
+    # The matching of the name to a converter should follow:
+    #   1) full, exact match
+    #   2) match of decorated, unqualified type
+    #   3) accept const ref as by value
+    #   4) accept ref as pointer
+    #   5) generalized cases (covers basically all user classes)
+
     try:
         return _converters[name]
     except KeyError:
         pass
-    
-    raise TypeError("no clue what %s is" % name)
+    compound = helper.compound(name)
+    cpptype = interp_cppyy.type_byname(space, helper.clean_type(name))
+    if compound == "*":
+        return InstancePtrConverter(space, cpptype)
+
+    print name
+
+    raise OperationError(space.w_TypeError, space.wrap("no clue what %s is" % name))
 
 _converters["int"]                 = IntConverter()
 _converters["double"]              = DoubleConverter()

Modified: pypy/branch/reflex-support/pypy/module/cppyy/executor.py
==============================================================================
--- pypy/branch/reflex-support/pypy/module/cppyy/executor.py	(original)
+++ pypy/branch/reflex-support/pypy/module/cppyy/executor.py	Thu Jul  8 19:37:02 2010
@@ -32,7 +32,7 @@
         result = capi.charp2str_free(ccpresult)
         return space.wrap(result)
 
-def get_executor(name):
+def get_executor(space, name):
     try:
         return _executors[name]
     except KeyError:

Added: pypy/branch/reflex-support/pypy/module/cppyy/helper.py
==============================================================================
--- (empty file)
+++ pypy/branch/reflex-support/pypy/module/cppyy/helper.py	Thu Jul  8 19:37:02 2010
@@ -0,0 +1,19 @@
+from pypy.rlib import rstring
+
+def compound(name):
+    name = "".join(rstring.split(name, "const")) # poor man's replace
+    i = _find_qualifier_index(name)
+    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 == ">":
+            break
+    return i + 1
+
+def clean_type(name):
+    assert name.find("const") == -1
+    i = _find_qualifier_index(name)
+    return name[:i].strip()

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	Thu Jul  8 19:37:02 2010
@@ -27,6 +27,8 @@
     char* arg_type_method(cppyy_typehandle_t handle, int method_index, int index);
     int is_constructor(cppyy_typehandle_t handle, int method_index);
     int is_static(cppyy_typehandle_t handle, int method_index);
+    int is_subtype(cppyy_typehandle_t h1, cppyy_typehandle_t h2);
+
     cppyy_typehandle_t dynamic_type(cppyy_typehandle_t handle, cppyy_object_t self);
 
     void myfree(void* ptr);

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	Thu Jul  8 19:37:02 2010
@@ -20,10 +20,23 @@
     return W_CPPLibrary(space, cdll)
 load_lib.unwrap_spec = [ObjSpace, str]
 
+class State(object):
+    def __init__(self, space):
+        self.cpptype_cache = {}
+
 def type_byname(space, name):
+    state = space.fromcache(State)
+    try:
+        return state.cpptype_cache[name]
+    except KeyError:
+        pass
+
     handle = capi.c_cppyy_get_typehandle(name)
     if handle:
-        return W_CPPType(space, name, handle)
+        cpptype = W_CPPType(space, name, handle)
+        state.cpptype_cache[name] = cpptype
+        return cpptype
+
     raise OperationError(space.w_TypeError, space.wrap("no such C++ class %s" % name))
 type_byname.unwrap_spec = [ObjSpace, str]
 
@@ -48,7 +61,7 @@
         self.space = cpptype.space
         self.method_index = method_index
         self.arg_types = arg_types
-        self.executor = executor.get_executor( result_type )
+        self.executor = executor.get_executor(self.space, result_type)
         self.arg_converters = None
         # <hack>
         self.hack_call = arg_types == ['int'] and result_type == 'int'
@@ -88,7 +101,7 @@
         return space.wrap(rffi.cast(lltype.Signed, result))
 
     def _build_converters(self):
-        self.arg_converters = [converter.get_converter(arg_type)
+        self.arg_converters = [converter.get_converter(self.space, arg_type)
                                    for arg_type in self.arg_types]
 
     @jit.unroll_safe
@@ -261,6 +274,8 @@
     construct = interp2app(W_CPPType.construct, unwrap_spec=['self', 'args_w']),
 )
 
+
+
 class W_CCPInstance(Wrappable):
     _immutable_ = True
     def __init__(self, cppclass, rawobject):

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	Thu Jul  8 19:37:02 2010
@@ -147,6 +147,14 @@
     return m.IsStatic();
 }
 
+int 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);
+}
+
 cppyy_typehandle_t dynamic_type(cppyy_typehandle_t handle, cppyy_object_t self) {
     Reflex::Type t((Reflex::TypeName*)handle);
     const Reflex::Object* obj = (const Reflex::Object*)self;

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	Thu Jul  8 19:37:02 2010
@@ -19,6 +19,8 @@
     def test_class_query(self):
         lib = interp_cppyy.load_lib(space, shared_lib)
         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"]
         func, = adddouble.functions
         assert isinstance(func.executor, executor.DoubleExecutor)

Added: pypy/branch/reflex-support/pypy/module/cppyy/test/test_helper.py
==============================================================================
--- (empty file)
+++ pypy/branch/reflex-support/pypy/module/cppyy/test/test_helper.py	Thu Jul  8 19:37:02 2010
@@ -0,0 +1,11 @@
+from pypy.module.cppyy import helper
+
+def test_compound():
+    assert helper.compound("int*") == "*"
+    assert helper.compound("int* const *&") == "**&"
+    assert helper.compound("std::vector<int>*") == "*"
+
+
+def test_clean_type():
+    assert helper.clean_type(" int***") == "int"
+    assert helper.clean_type("std::vector<int>&") == "std::vector<int>"

Modified: pypy/branch/reflex-support/pypy/module/cppyy/test/test_pythonify.py
==============================================================================
--- pypy/branch/reflex-support/pypy/module/cppyy/test/test_pythonify.py	(original)
+++ pypy/branch/reflex-support/pypy/module/cppyy/test/test_pythonify.py	Thu Jul  8 19:37:02 2010
@@ -128,7 +128,12 @@
 
         e = example01_class(14)
         pl = payload_class(3.14)
+        assert round(pl.getData()-3.14, 8) == 0
 
+        example01_class.setPayload(pl._cppinstance, 41.)
+        assert pl.getData() == 41.
+        example01_class.setPayload(pl, 43.)
+        assert pl.getData() == 43.
 
         pl.destruct()
         e.destruct()



More information about the Pypy-commit mailing list