[pypy-commit] pypy reflex-support: o) prepared some more tests for future dev

wlav noreply at buildbot.pypy.org
Fri Feb 17 23:40:07 CET 2012


Author: Wim Lavrijsen <WLavrijsen at lbl.gov>
Branch: reflex-support
Changeset: r52595:074e97fc7fc9
Date: 2012-02-17 14:39 -0800
http://bitbucket.org/pypy/pypy/changeset/074e97fc7fc9/

Log:	o) prepared some more tests for future dev o) std::string returns as
	python str o) string comparisons

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
@@ -130,6 +130,11 @@
     [C_TYPEHANDLE, rffi.INT, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.DOUBLE,
     compilation_info=backend.eci)
 
+c_call_s = rffi.llexternal(
+    "cppyy_call_s",
+    [C_TYPEHANDLE, rffi.INT, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.CCHARP,
+    compilation_info=backend.eci)
+
 c_get_methptr_getter = rffi.llexternal(
     "cppyy_get_methptr_getter",
     [C_TYPEHANDLE, rffi.INT], C_METHPTRGETTER_PTR,
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
@@ -269,6 +269,18 @@
         raise FastCallNotPossible
 
 
+class StdStringExecutor(InstancePtrExecutor):
+    _immutable_ = True
+
+    def execute(self, space, w_returntype, func, cppthis, num_args, args):
+        charp_result = capi.c_call_s(func.cpptype.handle, func.method_index, cppthis, num_args, args)
+        return space.wrap(capi.charp2str_free(charp_result))
+
+    def execute_libffi(self, space, w_returntype, libffifunc, argchain):
+        from pypy.module.cppyy.interp_cppyy import FastCallNotPossible
+        raise FastCallNotPossible
+
+
 _executors = {}
 def get_executor(space, name):
     # Matching of 'name' to an executor factory goes through up to four levels:
@@ -355,3 +367,6 @@
 _executors["float*"]              = FloatPtrExecutor
 _executors["double"]              = DoubleExecutor
 _executors["double*"]             = DoublePtrExecutor
+
+# special cases
+_executors["std::basic_string<char>"]        = StdStringExecutor
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
@@ -30,6 +30,8 @@
     double cppyy_call_f(cppyy_typehandle_t handle, int method_index, cppyy_object_t self, int numargs, void* args);
     double cppyy_call_d(cppyy_typehandle_t handle, int method_index, cppyy_object_t self, int numargs, void* args);
 
+    char*  cppyy_call_s(cppyy_typehandle_t handle, int method_index, cppyy_object_t self, int numargs, void* args);
+
     cppyy_methptrgetter_t cppyy_get_methptr_getter(cppyy_typehandle_t handle, int method_index);
 
     /* handling of function argument buffer */
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
@@ -250,6 +250,15 @@
             raise StopIteration
         pyclass.__iter__ = __iter__
 
+    # string comparisons
+    if pyclass.__name__ == 'std::string':
+        def eq(self, other):
+            if type(other) == pyclass:
+                return self.c_str() == other.c_str()
+            else:
+                return self.c_str() == other
+        pyclass.__eq__ = eq 
+
 
 _loaded_dictionaries = {}
 def load_reflection_info(name):
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
@@ -155,6 +155,20 @@
     return cppyy_call_T<double>(handle, method_index, self, numargs, args);
 }   
 
+char* cppyy_call_s(cppyy_typehandle_t handle, int method_index,
+                   cppyy_object_t self, int numargs, void* args) {
+    std::string result("");
+    std::vector<void*> arguments = build_args(numargs, args);
+    Reflex::Scope s = scope_from_handle(handle);
+    Reflex::Member m = s.FunctionMemberAt(method_index);
+    if (self) {
+        Reflex::Object o((Reflex::Type)s, self);
+        m.Invoke(o, result, arguments);
+    } else {
+       m.Invoke(result, arguments);
+    }
+    return cppstring_to_cstring(result);
+}
 
 static cppyy_methptrgetter_t get_methptr_getter(Reflex::Member m) {
     Reflex::PropertyList plist = m.Properties();
diff --git a/pypy/module/cppyy/test/stltypes.cxx b/pypy/module/cppyy/test/stltypes.cxx
--- a/pypy/module/cppyy/test/stltypes.cxx
+++ b/pypy/module/cppyy/test/stltypes.cxx
@@ -11,6 +11,16 @@
                          const std::STLTYPE< TTYPE >::iterator&);               \
 }
 
+
 //- explicit instantiations of used types
 STLTYPES_EXPLICIT_INSTANTIATION(vector, int)
 STLTYPES_EXPLICIT_INSTANTIATION(vector, just_a_class)
+
+//- class with lots of std::string handling
+stringy_class::stringy_class(const char* s) : m_string(s) {}
+
+std::string stringy_class::get_string1() { return m_string; }
+void stringy_class::get_string2(std::string& s) { s = m_string; }
+
+void stringy_class::set_string1(const std::string& s) { m_string = s; }
+void stringy_class::set_string2(std::string s) { m_string = s; }
diff --git a/pypy/module/cppyy/test/stltypes.h b/pypy/module/cppyy/test/stltypes.h
--- a/pypy/module/cppyy/test/stltypes.h
+++ b/pypy/module/cppyy/test/stltypes.h
@@ -25,3 +25,18 @@
 //- explicit instantiations of used types
 STLTYPES_EXPLICIT_INSTANTIATION_DECL(vector, int)
 STLTYPES_EXPLICIT_INSTANTIATION_DECL(vector, just_a_class)
+
+
+//- class with lots of std::string handling
+class stringy_class {
+public:
+   stringy_class(const char* s);
+
+   std::string get_string1();
+   void get_string2(std::string& s);
+
+   void set_string1(const std::string& s);
+   void set_string2(std::string s);
+
+   std::string m_string;
+};
diff --git a/pypy/module/cppyy/test/stltypes.xml b/pypy/module/cppyy/test/stltypes.xml
--- a/pypy/module/cppyy/test/stltypes.xml
+++ b/pypy/module/cppyy/test/stltypes.xml
@@ -1,5 +1,7 @@
 <lcgdict>
 
+  <namespace name="std" />
+
   <class pattern="std::vector<*>" />
   <class pattern="__gnu_cxx::__normal_iterator<*>" />
   <class pattern="__gnu_cxx::new_allocator<*>" />
@@ -12,4 +14,7 @@
 
   <class name="just_a_class" />
 
+  <class name="std::string" />
+  <class name="stringy_class" />
+
 </lcgdict>
diff --git a/pypy/module/cppyy/test/test_overloads.py b/pypy/module/cppyy/test/test_overloads.py
--- a/pypy/module/cppyy/test/test_overloads.py
+++ b/pypy/module/cppyy/test/test_overloads.py
@@ -86,10 +86,10 @@
         cc_ol = cppyy.gbl.cc_ol
 #        dd_ol = cppyy.gbl.dd_ol
 
-        assert more_overloads().call(aa_ol()).c_str() == "aa_ol"
-#        assert more_overloads().call(bb_ol()).c_str() == "dd_ol"    # <- bb_ol has an unknown + void*
-        assert more_overloads().call(cc_ol()).c_str() == "cc_ol"
-#        assert more_overloads().call(dd_ol()).c_str() == "dd_ol"    # <- dd_ol has an unknown
+        assert more_overloads().call(aa_ol()) == "aa_ol"
+#        assert more_overloads().call(bb_ol()) == "dd_ol"    # <- bb_ol has an unknown + void*
+        assert more_overloads().call(cc_ol()) == "cc_ol"
+#        assert more_overloads().call(dd_ol()) == "dd_ol"    # <- dd_ol has an unknown
 
     def test04_fully_fragile_overloads(self):
         """Test that unknown* is preferred over unknown&"""
@@ -130,7 +130,7 @@
         import cppyy
         more_overloads = cppyy.gbl.more_overloads
 
-#        assert more_overloads().call(1).c_str()   == "int"
-#        assert more_overloads().call(1.).c_str()  == "double"
-        assert more_overloads().call1(1).c_str()  == "int"
-        assert more_overloads().call1(1.).c_str() == "double"
+#        assert more_overloads().call(1)   == "int"
+#        assert more_overloads().call(1.)  == "double"
+        assert more_overloads().call1(1)  == "int"
+        assert more_overloads().call1(1.) == "double"
diff --git a/pypy/module/cppyy/test/test_pythonify.py b/pypy/module/cppyy/test/test_pythonify.py
--- a/pypy/module/cppyy/test/test_pythonify.py
+++ b/pypy/module/cppyy/test/test_pythonify.py
@@ -253,9 +253,9 @@
         # NOTE: when called through the stub, default args are fine
         f = a.stringRef
         s = cppyy.gbl.std.string
-        assert f(s("aap"), 0, s("noot")).c_str() == "aap"
-        assert f(s("noot"), 1).c_str() == "default"
-        assert f(s("mies")).c_str() == "mies"
+        assert f(s("aap"), 0, s("noot")) == "aap"
+        assert f(s("noot"), 1) == "default"
+        assert f(s("mies")) == "mies"
 
         for itype in ['short', 'ushort', 'int', 'uint', 'long', 'ulong']:
             g = getattr(a, '%sValue' % itype)
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
@@ -14,13 +14,13 @@
     if err:
         raise OSError("'make' failed (see stderr)")
 
-class AppTestSTL:
+class AppTestSTLVECTOR:
     def setup_class(cls):
         cls.space = space
         env = os.environ
         cls.w_N = space.wrap(13)
         cls.w_test_dct  = space.wrap(test_dct)
-        cls.w_datatypes = cls.space.appexec([], """():
+        cls.w_stlvector = cls.space.appexec([], """():
             import cppyy
             return cppyy.load_reflection_info(%r)""" % (test_dct, ))
 
@@ -129,3 +129,83 @@
         assert list(v) == [i for i in range(self.N)]
 
         v.destruct()
+
+
+class AppTestSTLSTRING:
+    def setup_class(cls):
+        cls.space = space
+        env = os.environ
+        cls.w_test_dct  = space.wrap(test_dct)
+        cls.w_stlstring = cls.space.appexec([], """():
+            import cppyy
+            return cppyy.load_reflection_info(%r)""" % (test_dct, ))
+
+    def test01_string_argument_passing(self):
+        """Test mapping of python strings and std::string"""
+
+        import cppyy
+        std = cppyy.gbl.std
+        stringy_class = cppyy.gbl.stringy_class
+
+        c, s = stringy_class(""), std.string("test1")
+
+        # pass through const std::string&
+        c.set_string1(s)
+        assert c.get_string1() == s
+
+        return
+
+        c.set_string1("test2")
+        assert c.get_string1() == "test2"
+
+        # pass through std::string (by value)
+        s = std.string("test3")
+        c.set_string2(s)
+        assert c.get_string1() == s
+
+        c.set_string2("test4")
+        assert c.get_string1() == "test4"
+
+        # getting through std::string&
+        s2 = std.string()
+        c.get_string2(s2)
+        assert s2 == "test4"
+
+        raises(TypeError, c.get_string2, "temp string")
+
+    def test02_string_data_ccess(self):
+        """Test access to std::string object data members"""
+
+        import cppyy
+        std = cppyy.gbl.std
+        stringy_class = cppyy.gbl.stringy_class
+
+        return
+
+        c, s = stringy_class(""), std.string("test string")
+
+        c.m_string = s
+        assert c.m_string == s
+        assert c.get_string1() == s
+
+        c.m_string = "another test"
+        assert c.m_string == "another test"
+        assert c.get_string1() == "another test"
+
+    def test03_string_with_null_character(self):
+        """Test that strings with NULL do not get truncated"""
+
+        import cppyy
+        std = cppyy.gbl.std
+        stringy_class = cppyy.gbl.stringy_class
+
+        return
+
+        t0 = "aap\0noot"
+        self.assertEqual(t0, "aap\0noot")
+
+        c, s = stringy_class(""), std.string(t0, len(t0))
+
+        c.set_string1(s)
+        assert t0 == c.get_string1()
+        assert s == c.get_string1()


More information about the pypy-commit mailing list