[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