[pypy-commit] pypy sepcomp2: Implement method calls across dll boundaries
amauryfa
noreply at buildbot.pypy.org
Wed Feb 22 23:24:32 CET 2012
Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: sepcomp2
Changeset: r52775:cdad5637ce91
Date: 2012-02-22 23:21 +0100
http://bitbucket.org/pypy/pypy/changeset/cdad5637ce91/
Log: Implement method calls across dll boundaries
diff --git a/pypy/translator/c/exportinfo.py b/pypy/translator/c/exportinfo.py
--- a/pypy/translator/c/exportinfo.py
+++ b/pypy/translator/c/exportinfo.py
@@ -115,8 +115,10 @@
_about_ = convert
def compute_result_annotation(self, s_arg):
- if not (isinstance(s_arg, SomeControlledInstance) and
- s_arg.s_real_obj.ll_ptrtype == TARGET):
+ if not ((isinstance(s_arg, SomeControlledInstance) and
+ s_arg.s_real_obj.ll_ptrtype == TARGET) or
+ (isinstance(s_arg, model.SomePtr) and
+ s_arg.ll_ptrtype == TARGET)):
raise TypeError("Expected a proxy for %s" % (TARGET,))
return model.lltype_to_annotation(TARGET)
@@ -134,7 +136,7 @@
self.cls = cls
def make_constructor(self):
- self.constructor_name = "__new__%s" % (self.name,)
+ function_name = "__new__%s" % (self.name,)
nbargs = len(self.cls.__init__.argtypes)
args = ', '.join(['arg%d' % d for d in range(nbargs)])
source = py.code.Source(r"""
@@ -142,14 +144,25 @@
obj = instantiate(cls)
obj.__init__(%s)
return obj
- """ % (self.constructor_name, args, args))
+ """ % (function_name, args, args))
miniglobals = {'cls': self.cls, 'instantiate': instantiate}
exec source.compile() in miniglobals
- constructor = miniglobals[self.constructor_name]
+ constructor = miniglobals[function_name]
constructor._always_inline_ = True
constructor.argtypes = self.cls.__init__.argtypes
return constructor
+ def make_exported_methods(self):
+ self.methods = {}
+ for meth_name, method in self.cls.__dict__.items():
+ if not getattr(method, 'exported', None):
+ continue
+ if meth_name == '__init__':
+ method = self.make_constructor()
+ else:
+ method.argtypes = (self.cls,) + method.argtypes
+ self.methods[meth_name] = method
+
def save_repr(self, builder):
rtyper = builder.db.translator.rtyper
bookkeeper = rtyper.annotator.bookkeeper
@@ -162,14 +175,16 @@
will intercept all operations on the class."""
STRUCTPTR = self.classrepr
- constructor = getattr(module, self.constructor_name)
-
class ClassController(Controller):
knowntype = STRUCTPTR
+ def install_constructor(constructor):
def new(self, *args):
return constructor(*args)
-
+ ClassController.new = new
+ if '__init__' in self.methods:
+ install_constructor(self.methods['__init__'])
+
def install_attribute(name):
def getter(self, obj):
return getattr(obj, 'inst_' + name)
@@ -180,6 +195,13 @@
for name, attrdef in self.classdef.attrs.items():
install_attribute(name)
+ def install_method(name, method):
+ def method_call(self, obj, *args):
+ method(obj, *args)
+ setattr(ClassController, 'method_' + name, method_call)
+ for name, method in self.methods.items():
+ install_method(name, method)
+
class Entry(ControllerEntry):
_about_ = self.cls
_controller_ = ClassController
@@ -210,10 +232,12 @@
"""Annotate all exported functions."""
bk = annotator.bookkeeper
- # annotate constructors of exported classes
+ # annotate methods of exported classes
for name, class_info in self.classes.items():
- constructor = class_info.make_constructor()
- self.add_function(constructor.__name__, constructor)
+ class_info.make_exported_methods()
+ for meth_name, method in class_info.methods.items():
+ self.add_function(meth_name, method)
+
# annotate functions with signatures
for name, func_info in self.functions.items():
diff --git a/pypy/translator/c/test/test_export.py b/pypy/translator/c/test/test_export.py
--- a/pypy/translator/c/test/test_export.py
+++ b/pypy/translator/c/test/test_export.py
@@ -143,3 +143,22 @@
return s.x
mod = self.compile_module("second", g=g)
assert mod.g() == 36.2
+
+ def test_method_call(self):
+ class Struct:
+ @export(float)
+ def __init__(self, x):
+ self.x = x
+ @export()
+ def increment(self):
+ self.x += 33.2
+ self.compile_module("first", Struct=Struct)
+
+ @export()
+ def g():
+ s = Struct(3.0)
+ s.increment()
+ return s.x
+ mod = self.compile_module("second", g=g)
+ assert mod.g() == 36.2
+
More information about the pypy-commit
mailing list