[pypy-svn] r25819 - in pypy/dist/pypy/rpython: . lltypesystem rctypes rctypes/test

arigo at codespeak.net arigo at codespeak.net
Thu Apr 13 22:36:11 CEST 2006


Author: arigo
Date: Thu Apr 13 22:36:09 2006
New Revision: 25819

Modified:
   pypy/dist/pypy/rpython/extregistry.py
   pypy/dist/pypy/rpython/lltypesystem/lltype.py
   pypy/dist/pypy/rpython/rctypes/rfunc.py
   pypy/dist/pypy/rpython/rctypes/rpointer.py
   pypy/dist/pypy/rpython/rctypes/test/test_rctypes.py
Log:
extregistry support for things that cannot be weakly referenced,
like built-in functions (duh).  In rctypes, byref() and functions
taking 'struct' arguments.


Modified: pypy/dist/pypy/rpython/extregistry.py
==============================================================================
--- pypy/dist/pypy/rpython/extregistry.py	(original)
+++ pypy/dist/pypy/rpython/extregistry.py	Thu Apr 13 22:36:09 2006
@@ -21,6 +21,8 @@
         return self.compute_annotation(type, instance)
     
 EXT_REGISTRY_BY_VALUE = weakref.WeakKeyDictionary()
+EXT_REGISTRY_BY_VALUE_NONWEAK = {}    # for things that cannot be weakly ref'ed
+                                      # like built-in functions
 EXT_REGISTRY_BY_TYPE = weakref.WeakKeyDictionary()
 EXT_REGISTRY_BY_METATYPE = weakref.WeakKeyDictionary()
 
@@ -46,9 +48,15 @@
             get_repr)
 
 def register_value(value, **kwargs):
-    assert value not in EXT_REGISTRY_BY_VALUE
-    EXT_REGISTRY_BY_VALUE[value] = create_entry(**kwargs)
-    return EXT_REGISTRY_BY_VALUE[value]
+    try:
+        weakref.ref(value)
+    except TypeError:
+        REG = EXT_REGISTRY_BY_VALUE_NONWEAK
+    else:
+        REG = EXT_REGISTRY_BY_VALUE
+    assert value not in REG
+    REG[value] = create_entry(**kwargs)
+    return REG[value]
     
 def register_type(t, **kwargs):
     assert t not in EXT_REGISTRY_BY_TYPE
@@ -75,7 +83,13 @@
 
 def lookup(instance):
     try:
-        return EXT_REGISTRY_BY_VALUE[instance]
+        weakref.ref(instance)
+    except TypeError:
+        REG = EXT_REGISTRY_BY_VALUE_NONWEAK
+    else:
+        REG = EXT_REGISTRY_BY_VALUE
+    try:
+        return REG[instance]
     except (KeyError, TypeError):
         return lookup_type(type(instance))
         

Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lltype.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/lltype.py	Thu Apr 13 22:36:09 2006
@@ -379,8 +379,9 @@
     def __init__(self, args, result):
         for arg in args:
             assert isinstance(arg, LowLevelType)
-            if isinstance(arg, ContainerType):
-                raise TypeError, "function arguments can only be primitives or pointers"
+            # -- disabled the following check for the benefits of rctypes --
+            #if isinstance(arg, ContainerType):
+            #    raise TypeError, "function arguments can only be primitives or pointers"
         self.ARGS = tuple(args)
         assert isinstance(result, LowLevelType)
         if isinstance(result, ContainerType):

Modified: pypy/dist/pypy/rpython/rctypes/rfunc.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/rfunc.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/rfunc.py	Thu Apr 13 22:36:09 2006
@@ -1,5 +1,6 @@
 from pypy.annotation import model as annmodel
 from pypy.rpython import extregistry
+from pypy.rpython.rctypes.rmodel import CTypesValueRepr
 
 import ctypes
 
@@ -35,8 +36,17 @@
         args_r.append(r_arg)
 
     vlist = hop.inputargs(*args_r)
-    unwrapped_args_v = [r_arg.getvalue(hop.llops, v)
-                        for r_arg, v in zip(args_r, vlist)]
+    unwrapped_args_v = []
+    for r_arg, v in zip(args_r, vlist):
+        if isinstance(r_arg, CTypesValueRepr):
+            # ValueRepr case
+            unwrapped_args_v.append(r_arg.getvalue(hop.llops, v))
+        else:
+            # RefRepr case -- i.e. the function argument that we pass by
+            # value is e.g. a complete struct; we pass a pointer to it
+            # in the low-level graphs and it's up to the back-end to
+            # generate the correct dereferencing
+            unwrapped_args_v.append(r_arg.get_c_data(hop.llops, v))
     s_res = annmodel.SomeCTypesObject(cfuncptr.restype,
                                       annmodel.SomeCTypesObject.OWNSMEMORY)
     r_res = hop.rtyper.getrepr(s_res)

Modified: pypy/dist/pypy/rpython/rctypes/rpointer.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/rpointer.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/rpointer.py	Thu Apr 13 22:36:09 2006
@@ -6,7 +6,7 @@
 from pypy.annotation.pairtype import pairtype
 from pypy.rpython.rctypes.rmodel import CTypesValueRepr, genreccopy
 
-from ctypes import POINTER, pointer, c_int
+from ctypes import POINTER, pointer, byref, c_int
 
 class PointerRepr(CTypesValueRepr):
     def __init__(self, rtyper, s_pointer):
@@ -140,3 +140,9 @@
         # same rtyping for calling pointer() or calling a specific instance
         # of PointerType:
         specialize_call=pointertype_specialize_call)
+
+# byref() is equivalent to pointer() -- the difference is only an
+# optimization that is useful in ctypes but not in rctypes.
+extregistry.register_value(byref,
+        compute_result_annotation=pointerfn_compute_annotation,
+        specialize_call=pointertype_specialize_call)

Modified: pypy/dist/pypy/rpython/rctypes/test/test_rctypes.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/test/test_rctypes.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/test/test_rctypes.py	Thu Apr 13 22:36:09 2006
@@ -3,6 +3,7 @@
 """
 
 import py
+import pypy.rpython.rctypes.implementation
 from pypy.annotation.annrpython import RPythonAnnotator
 from pypy.translator.translator import TranslationContext
 from pypy.translator.c.test.test_genc import compile, compile_db
@@ -21,7 +22,7 @@
 
 
 from ctypes import cdll
-from ctypes import POINTER, Structure, c_int
+from ctypes import POINTER, Structure, c_int, byref
 
 # __________ compile and load our local test C file __________
 
@@ -48,7 +49,14 @@
 # _testfunc_byval
 testfunc_byval = _rctypes_test._testfunc_byval
 testfunc_byval.restype = c_int
-testfunc_byval.argtypes = [tagpoint,POINTER(tagpoint)]
+testfunc_byval.argtypes = [tagpoint, POINTER(tagpoint)]
+
+def ll_testfunc_byval(in_, pout):
+    if pout:
+        pout.x = in_.x
+        pout.y = in_.y
+    return in_.x + in_.y
+testfunc_byval.llinterp_friendly_version = ll_testfunc_byval
 
 # _test_struct
 testfunc_struct = _rctypes_test._testfunc_struct
@@ -67,4 +75,24 @@
 testfunc_struct_pointer_id.argtypes = [tagpointptr]
 
 
-# XXX no test here so far
+def test_rctypes_dll():     # this test is also annotated/specialized below
+    in_point = tagpoint()
+    in_point.x = 42
+    in_point.y = 17
+    out_point = tagpoint()
+    res = testfunc_byval(in_point, byref(out_point))
+    assert res == in_point.x + in_point.y
+    assert out_point.x == 42
+    assert out_point.y == 17
+
+class Test_annotation:
+    def test_annotate_byval(self):
+        t = TranslationContext()
+        a = t.buildannotator()
+        s = a.build_types(test_rctypes_dll, [])
+        if conftest.option.view:
+            t.view()
+
+class Test_specialization:
+    def test_specialize_byval(self):
+        interpret(test_rctypes_dll, [])



More information about the Pypy-commit mailing list