[pypy-commit] pypy reflex-support: allow python str to pass through std::string and const std::string&

wlav noreply at buildbot.pypy.org
Sat Feb 18 06:36:05 CET 2012


Author: Wim Lavrijsen <WLavrijsen at lbl.gov>
Branch: reflex-support
Changeset: r52597:a11f7dc9ad01
Date: 2012-02-17 16:23 -0800
http://bitbucket.org/pypy/pypy/changeset/a11f7dc9ad01/

Log:	allow python str to pass through std::string and const std::string&

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
@@ -244,3 +244,18 @@
     voidp = rffi.cast(rffi.VOIDP, charp)
     c_free(voidp)
     return string
+
+c_charp2stdstring = rffi.llexternal(
+    "cppyy_charp2stdstring",
+    [rffi.CCHARP], rffi.VOIDP,
+    compilation_info=backend.eci)
+
+c_stdstring2stdstring = rffi.llexternal(
+    "cppyy_stdstring2stdstring",
+    [rffi.VOIDP], rffi.VOIDP,
+    compilation_info=backend.eci)
+
+c_free_stdstring = rffi.llexternal(
+    "cppyy_free_stdstring",
+    [rffi.VOIDP], lltype.Void,
+    compilation_info=backend.eci)
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
@@ -1,5 +1,7 @@
 import sys
 
+from pypy.interpreter.error import OperationError
+
 from pypy.rpython.lltypesystem import rffi, lltype
 from pypy.rlib.rarithmetic import r_singlefloat
 from pypy.rlib import jit, libffi, clibffi, rfloat
@@ -532,6 +534,36 @@
         return interp_cppyy.new_instance(space, w_type, self.cpptype, address, False)
 
 
+class StdStringConverter(InstanceConverter):
+    _immutable_ = True
+
+    def __init__(self, space, extra):
+        from pypy.module.cppyy import interp_cppyy
+        cpptype = interp_cppyy.type_byname(space, "std::string")
+        InstanceConverter.__init__(self, space, cpptype, "std::string")
+
+    def _unwrap_object(self, space, w_obj):
+        try:
+           charp = rffi.str2charp(space.str_w(w_obj))
+           arg = capi.c_charp2stdstring(charp)
+           rffi.free_charp(charp)
+           return arg
+        except OperationError:
+           arg = InstanceConverter._unwrap_object(self, space, w_obj)
+           return capi.c_stdstring2stdstring(arg)
+
+    def free_argument(self, arg):
+        capi.c_free_stdstring(rffi.cast(rffi.VOIDPP, arg)[0])
+
+class StdStringRefConverter(InstancePtrConverter):
+    _immutable_ = True
+
+    def __init__(self, space, extra):
+        from pypy.module.cppyy import interp_cppyy
+        cpptype = interp_cppyy.type_byname(space, "std::string")
+        InstancePtrConverter.__init__(self, space, cpptype, "std::string")
+
+
 _converters = {}         # builtin and custom types
 _a_converters = {}       # array and ptr versions of above
 def get_converter(space, name, default):
@@ -614,6 +646,14 @@
 _converters["void**"]                   = VoidPtrPtrConverter
 _converters["void*&"]                   = VoidPtrRefConverter
 
+# special cases
+_converters["std::string"]                       = StdStringConverter
+_converters["std::basic_string<char>"]           = StdStringConverter
+_converters["const std::string&"]                = StdStringConverter     # TODO: shouldn't copy
+_converters["const std::basic_string<char>&"]    = StdStringConverter
+_converters["std::string&"]                      = StdStringRefConverter
+_converters["std::basic_string<char>&"]          = StdStringRefConverter
+
 # it should be possible to generate these:
 _a_converters["short int*"]               = ShortPtrConverter
 _a_converters["short*"]                   = _a_converters["short int*"]
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
@@ -79,6 +79,10 @@
     long long cppyy_strtoll(const char* str);
     unsigned long long cppyy_strtuoll(const char* str);
 
+    void* cppyy_charp2stdstring(const char* str);
+    void* cppyy_stdstring2stdstring(void* ptr);
+    void cppyy_free_stdstring(void* ptr);
+
 #ifdef __cplusplus
 }
 #endif // 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
@@ -408,3 +408,16 @@
 void cppyy_free(void* ptr) {
     free(ptr);
 }
+
+void* cppyy_charp2stdstring(const char* str) {
+    return new std::string(str);
+}
+
+void* cppyy_stdstring2stdstring(void* ptr) {
+    return new std::string(*(std::string*)ptr);
+}
+
+void cppyy_free_stdstring(void* ptr) {
+    delete (std::string*)ptr;
+}
+
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
@@ -153,8 +153,6 @@
         c.set_string1(s)
         assert c.get_string1() == s
 
-        return
-
         c.set_string1("test2")
         assert c.get_string1() == "test2"
 


More information about the pypy-commit mailing list