[pypy-commit] pypy reflex-support: allow lookup and creation of pythonized classes at the interpreter level to finish dynamic return type implementation
wlav
noreply at buildbot.pypy.org
Wed Mar 14 14:27:02 CET 2012
Author: Wim Lavrijsen <WLavrijsen at lbl.gov>
Branch: reflex-support
Changeset: r53554:907ef031f4a4
Date: 2012-03-14 04:01 -0700
http://bitbucket.org/pypy/pypy/changeset/907ef031f4a4/
Log: allow lookup and creation of pythonized classes at the interpreter
level to finish dynamic return type implementation
diff --git a/pypy/module/cppyy/__init__.py b/pypy/module/cppyy/__init__.py
--- a/pypy/module/cppyy/__init__.py
+++ b/pypy/module/cppyy/__init__.py
@@ -8,6 +8,8 @@
'_resolve_name' : 'interp_cppyy.resolve_name',
'_type_byname' : 'interp_cppyy.type_byname',
'_template_byname' : 'interp_cppyy.template_byname',
+ '_set_class_generator' : 'interp_cppyy.set_class_generator',
+ '_register_class' : 'interp_cppyy.register_class',
'CPPInstance' : 'interp_cppyy.W_CPPInstance',
'addressof' : 'interp_cppyy.addressof',
'bind_object' : 'interp_cppyy.bind_object',
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
@@ -532,7 +532,7 @@
def from_memory(self, space, w_obj, w_type, offset):
address = rffi.cast(capi.C_OBJECT, self._get_raw_address(space, w_obj, offset))
from pypy.module.cppyy import interp_cppyy
- return interp_cppyy.new_instance(space, w_type, self.cpptype, address, True, False)
+ return interp_cppyy.wrap_cppobject_nocast(space, w_type, self.cpptype, address, True, False)
def to_memory(self, space, w_obj, w_value, offset):
address = rffi.cast(rffi.VOIDPP, self._get_raw_address(space, w_obj, offset))
@@ -544,7 +544,7 @@
def from_memory(self, space, w_obj, w_type, offset):
address = rffi.cast(capi.C_OBJECT, self._get_raw_address(space, w_obj, offset))
from pypy.module.cppyy import interp_cppyy
- return interp_cppyy.new_instance(space, w_type, self.cpptype, address, False, False)
+ return interp_cppyy.wrap_cppobject_nocast(space, w_type, self.cpptype, address, False, False)
def to_memory(self, space, w_obj, w_value, offset):
self._is_abstract(space)
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
@@ -248,12 +248,12 @@
from pypy.module.cppyy import interp_cppyy
long_result = capi.c_call_l(cppmethod, cppthis, num_args, args)
ptr_result = rffi.cast(capi.C_OBJECT, long_result)
- return interp_cppyy.new_instance(space, w_returntype, self.cpptype, ptr_result, False, False)
+ return interp_cppyy.wrap_cppobject(space, w_returntype, self.cpptype, ptr_result, False, False)
def execute_libffi(self, space, w_returntype, libffifunc, argchain):
from pypy.module.cppyy import interp_cppyy
ptr_result = rffi.cast(capi.C_OBJECT, libffifunc.call(argchain, rffi.VOIDP))
- return interp_cppyy.new_instance(space, w_returntype, self.cpptype, ptr_result, False, False)
+ return interp_cppyy.wrap_cppobject(space, w_returntype, self.cpptype, ptr_result, False, False)
class InstancePtrPtrExecutor(InstancePtrExecutor):
_immutable_ = True
@@ -263,7 +263,7 @@
voidp_result = capi.c_call_r(cppmethod, cppthis, num_args, args)
ref_address = rffi.cast(rffi.VOIDPP, voidp_result)
ptr_result = rffi.cast(capi.C_OBJECT, ref_address[0])
- return interp_cppyy.new_instance(space, w_returntype, self.cpptype, ptr_result, False, False)
+ return interp_cppyy.wrap_cppobject(space, w_returntype, self.cpptype, ptr_result, False, False)
def execute_libffi(self, space, w_returntype, libffifunc, argchain):
from pypy.module.cppyy.interp_cppyy import FastCallNotPossible
@@ -276,7 +276,7 @@
from pypy.module.cppyy import interp_cppyy
long_result = capi.c_call_o(cppmethod, cppthis, num_args, args, self.cpptype.handle)
ptr_result = rffi.cast(capi.C_OBJECT, long_result)
- return interp_cppyy.new_instance(space, w_returntype, self.cpptype, ptr_result, False, True)
+ return interp_cppyy.wrap_cppobject(space, w_returntype, self.cpptype, ptr_result, False, True)
def execute_libffi(self, space, w_returntype, libffifunc, argchain):
from pypy.module.cppyy.interp_cppyy import FastCallNotPossible
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
@@ -30,6 +30,8 @@
self.r_cppscope_cache = {
"void" : W_CPPType(space, "void", capi.C_NULL_TYPE) }
self.r_cpptemplate_cache = {}
+ self.type_registry = {}
+ self.w_clgen_callback = None
@unwrap_spec(name=str)
def resolve_name(space, name):
@@ -80,6 +82,18 @@
return None
+ at unwrap_spec(w_callback=W_Root)
+def set_class_generator(space, w_callback):
+ state = space.fromcache(State)
+ state.w_clgen_callback = w_callback
+
+ at unwrap_spec(w_type=W_Root)
+def register_class(space, w_type):
+ w_cpptype = space.findattr(w_type, space.wrap("_cpp_proxy"))
+ cpptype = space.interp_w(W_CPPType, w_cpptype, can_be_None=False)
+ state = space.fromcache(State)
+ state.type_registry[cpptype.handle] = w_type
+
class W_CPPLibrary(Wrappable):
_immutable_ = True
@@ -225,7 +239,7 @@
except Exception:
capi.c_deallocate(self.cpptype.handle, newthis)
raise
- return new_instance(self.space, w_type, self.cpptype, newthis, False, True)
+ return wrap_new_cppobject_nocast(self.space, w_type, self.cpptype, newthis, False, True)
class W_CPPOverload(Wrappable):
@@ -637,23 +651,34 @@
memory_regulator = MemoryRegulator()
-def new_instance(space, w_type, cpptype, rawobject, isref, python_owns):
- obj_actual = rawobject
- actual = cpptype.handle
+def wrap_new_cppobject_nocast(space, w_type, cpptype, rawobject, isref, python_owns):
+ w_cppinstance = space.allocate_instance(W_CPPInstance, w_type)
+ cppinstance = space.interp_w(W_CPPInstance, w_cppinstance, can_be_None=False)
+ W_CPPInstance.__init__(cppinstance, space, cpptype, rawobject, isref, python_owns)
+ memory_regulator.register(cppinstance)
+ return w_cppinstance
+
+def wrap_cppobject_nocast(space, w_type, cpptype, rawobject, isref, python_owns):
+ obj = memory_regulator.retrieve(rawobject)
+ if obj and obj.cppclass == cpptype:
+ return obj
+ return wrap_new_cppobject_nocast(space, w_type, cpptype, rawobject, isref, python_owns)
+
+def wrap_cppobject(space, w_type, cpptype, rawobject, isref, python_owns):
if rawobject:
actual = capi.c_get_object_type(cpptype.handle, rawobject)
if actual != cpptype.handle:
offset = capi.c_base_offset(actual, cpptype.handle, rawobject)
- obj_actual = capi.direct_ptradd(rawobject, offset)
- # TODO: fix-up w_type to be w_actual_type
- obj = memory_regulator.retrieve(obj_actual)
- if obj and obj.cppclass.handle == actual:# == cpptype:
- return obj
- w_cppinstance = space.allocate_instance(W_CPPInstance, w_type)
- cppinstance = space.interp_w(W_CPPInstance, w_cppinstance, can_be_None=False)
- W_CPPInstance.__init__(cppinstance, space, cpptype, obj_actual, isref, python_owns)
- memory_regulator.register(cppinstance)
- return w_cppinstance
+ rawobject = capi.direct_ptradd(rawobject, offset)
+ state = space.fromcache(State)
+ try:
+ w_type = state.type_registry[actual]
+ except KeyError:
+ final_name = capi.charp2str_free(capi.c_final_name(actual))
+ w_type = space.call_function(state.w_clgen_callback, space.wrap(final_name))
+ w_cpptype = space.findattr(w_type, space.wrap("_cpp_proxy"))
+ cpptype = space.interp_w(W_CPPType, w_cpptype, can_be_None=False)
+ return wrap_cppobject_nocast(space, w_type, cpptype, rawobject, isref, python_owns)
@unwrap_spec(cppinstance=W_CPPInstance)
def addressof(space, cppinstance):
@@ -665,9 +690,4 @@
rawobject = rffi.cast(capi.C_OBJECT, address)
w_cpptype = space.findattr(w_type, space.wrap("_cpp_proxy"))
cpptype = space.interp_w(W_CPPType, w_cpptype, can_be_None=False)
-
- obj = memory_regulator.retrieve(rawobject)
- if obj and obj.cppclass == cpptype:
- return obj
-
- return new_instance(space, w_type, cpptype, rawobject, False, owns)
+ return wrap_cppobject_nocast(space, w_type, cpptype, rawobject, False, owns)
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
@@ -43,6 +43,10 @@
return getattr(self._scope, fullname)
+def clgen_callback(name):
+ return get_cppclass(name)
+cppyy._set_class_generator(clgen_callback)
+
def make_static_function(cpptype, func_name, cppol):
rettype = cppol.get_returntype()
if not rettype: # return builtin type
@@ -196,6 +200,7 @@
setattr(metacpp, dm_name, pydm)
_pythonize(pycpptype)
+ cppyy._register_class(pycpptype)
return pycpptype
def make_cpptemplatetype(scope, template_name):
diff --git a/pypy/module/cppyy/test/advancedcpp.h b/pypy/module/cppyy/test/advancedcpp.h
--- a/pypy/module/cppyy/test/advancedcpp.h
+++ b/pypy/module/cppyy/test/advancedcpp.h
@@ -20,6 +20,7 @@
double get_base_value() { return m_db; }
virtual base_class* cycle(base_class* b) { return b; }
+ virtual base_class* clone() { return new base_class; }
public:
int m_b;
@@ -31,6 +32,7 @@
derived_class() { m_d = 2; m_dd = 2.2;}
virtual int get_value() { return m_d; }
double get_derived_value() { return m_dd; }
+ virtual base_class* clone() { return new derived_class; }
public:
int m_d;
diff --git a/pypy/module/cppyy/test/test_advancedcpp.py b/pypy/module/cppyy/test/test_advancedcpp.py
--- a/pypy/module/cppyy/test/test_advancedcpp.py
+++ b/pypy/module/cppyy/test/test_advancedcpp.py
@@ -430,3 +430,6 @@
assert isinstance(d.cycle(b), base_class)
assert isinstance(b.cycle(d), derived_class)
assert isinstance(d.cycle(d), derived_class)
+
+ assert isinstance(b.clone(), base_class) # TODO: clone() leaks
+ assert isinstance(d.clone(), derived_class) # TODO: clone() leaks
diff --git a/pypy/module/cppyy/test/test_zjit.py b/pypy/module/cppyy/test/test_zjit.py
--- a/pypy/module/cppyy/test/test_zjit.py
+++ b/pypy/module/cppyy/test/test_zjit.py
@@ -131,6 +131,9 @@
assert isinstance(w_type, FakeReturnType)
return instantiate(cls)
+ def call_function(self, w_func, *args_w):
+ return None
+
def _freeze_(self):
return True
More information about the pypy-commit
mailing list