[pypy-svn] r44976 - in pypy/dist/pypy/rpython/tool: . test

fijal at codespeak.net fijal at codespeak.net
Thu Jul 12 17:21:51 CEST 2007


Author: fijal
Date: Thu Jul 12 17:21:50 2007
New Revision: 44976

Modified:
   pypy/dist/pypy/rpython/tool/mkrffi.py
   pypy/dist/pypy/rpython/tool/test/test_c.py
   pypy/dist/pypy/rpython/tool/test/test_mkrffi.py
Log:
(simonb, fijal) Make this work for structures as well


Modified: pypy/dist/pypy/rpython/tool/mkrffi.py
==============================================================================
--- pypy/dist/pypy/rpython/tool/mkrffi.py	(original)
+++ pypy/dist/pypy/rpython/tool/mkrffi.py	Thu Jul 12 17:21:50 2007
@@ -9,20 +9,68 @@
 
 # XXX any automatic stuff here?
 SIMPLE_TYPE_MAPPING = {
-    ctypes.c_int : 'rffi.INT',
-    ctypes.c_voidp : primitive_pointer_repr('lltype.Void')
+    ctypes.c_int   : 'rffi.INT',
+    ctypes.c_uint  : 'rffi.UINT',
+    ctypes.c_voidp : 'rffi.VOIDP',
 }
 
-def proc_tp(tp):
-    try:
-        return SIMPLE_TYPE_MAPPING[tp]
-    except KeyError:
+class RffiSource(object):
+    def __init__(self, structures=None, code=None):
+        # ctypes structure -> code mapping
+        if structures is None:
+            self.structures = {}
+        else:
+            self.structures = structures
+        # rest of the code
+        if code is None:
+            self.code = py.code.Source()
+        else:
+            self.code = code
+
+    def __add__(self, other):
+        structs = self.structures.copy()
+        structs.update(other.structures)
+        code = py.code.Source(self.code, other.code)
+        return RffiSource(structs, code)
+
+    def __iadd__(self, other):
+        self.structures.update(other.structures)
+        self.code = py.code.Source(self.code, other.code)
+        return self
+
+    def proc_struct(self, tp):
+        name = tp.__name__
+        real_name = 'c_' + name
+        real_name = real_name.rstrip('_structure')
+        real_name += '_structure'
+        if tp not in self.structures:
+            fields = ["('%s', %s)" % (name_, self.proc_tp(field_tp))
+                      for name_, field_tp in tp._fields_]
+            fields_repr = ", ".join(fields)
+            self.structures[tp] = py.code.Source(
+                "%s = rffi.CStruct('%s', %s)"%(real_name, name,
+                                              fields_repr))
+        return real_name
+
+    def proc_tp(self, tp):
+        try:
+            return SIMPLE_TYPE_MAPPING[tp]
+        except KeyError:
+            pass
+        if issubclass(tp, ctypes._Pointer):
+            if issubclass(tp._type_, ctypes._SimpleCData):
+                return "lltype.Ptr(lltype.Array(%s, hints={'nolength': True}))"\
+                       % self.proc_tp(tp._type_)
+            return "lltype.Ptr(%s)" % self.proc_tp(tp._type_)
+        elif issubclass(tp, ctypes.Structure):
+            return self.proc_struct(tp)
         raise NotImplementedError("Not implemented mapping for %s" % tp)
 
-def proc_func(func):
-    name = func.__name__
-    src = py.code.Source("""
-    c_%s = rffi.llexternal('%s', [%s], %s)
-    """%(name, name, ",".join([proc_tp(arg) for arg in func.argtypes]),
-         proc_tp(func.restype)))
-    return src
+    def proc_func(self, func):
+        name = func.__name__
+        src = py.code.Source("""
+        c_%s = rffi.llexternal('%s', [%s], %s)
+        """%(name, name, ", ".join([self.proc_tp(arg) for
+                                   arg in func.argtypes]),
+             self.proc_tp(func.restype)))
+        self.code = py.code.Source(self.code, src)

Modified: pypy/dist/pypy/rpython/tool/test/test_c.py
==============================================================================
--- pypy/dist/pypy/rpython/tool/test/test_c.py	(original)
+++ pypy/dist/pypy/rpython/tool/test/test_c.py	Thu Jul 12 17:21:50 2007
@@ -8,6 +8,13 @@
 
 c_source = """
 void *int_to_void_p(int arg) {}
+
+struct random_strucutre {
+  int one;
+  int *two;
+};
+
+struct random_structure* int_int_to_struct_p(int one, int two) {}
 """
 
 class TestBasic:

Modified: pypy/dist/pypy/rpython/tool/test/test_mkrffi.py
==============================================================================
--- pypy/dist/pypy/rpython/tool/test/test_mkrffi.py	(original)
+++ pypy/dist/pypy/rpython/tool/test/test_mkrffi.py	Thu Jul 12 17:21:50 2007
@@ -4,15 +4,56 @@
 from pypy.rpython.tool.test.test_c import TestBasic
 import py
 
+class random_structure(ctypes.Structure):
+    _fields_ = [('one', ctypes.c_int),
+                ('two', ctypes.POINTER(ctypes.c_int))]
+
+def test_rffisource():
+    res = RffiSource({1:2, 3:4}, "ab") + RffiSource(None, "c")
+    assert res.structures == {1:2, 3:4}
+    assert str(res.code) == "ab\nc"
+    res += RffiSource({5:6})
+    assert 5 in res.structures.keys()
+
+def test_proc_tp_simple():
+    rffi_source = RffiSource()
+    assert rffi_source.proc_tp(ctypes.c_int) == 'rffi.INT'
+    assert rffi_source.proc_tp(ctypes.c_void_p) == 'rffi.VOIDP'
+
+def test_proc_tp_complicated():
+    rffi_source = RffiSource()    
+    assert rffi_source.proc_tp(ctypes.POINTER(ctypes.c_uint)) == \
+           "lltype.Ptr(lltype.Array(rffi.UINT, hints={'nolength': True}))"
+    rffi_source.proc_tp(random_structure)
+    _src = py.code.Source("""
+    c_random_structure = rffi.CStruct('random_structure', ('one', rffi.INT), ('two', lltype.Ptr(lltype.Array(rffi.INT, hints={'nolength': True}))))
+    """)
+    src = rffi_source.structures[random_structure]
+    assert src.strip() == _src.strip(), str(src) + "\n" + str(_src)
+
 class TestMkrffi(TestBasic):
     def test_single_func(self):
         func = self.lib.int_to_void_p
         func.argtypes = [ctypes.c_int]
         func.restype = ctypes.c_voidp
 
-        src = proc_func(func)
+        src = RffiSource()
+        src.proc_func(func)
         _src = py.code.Source("""
-        c_int_to_void_p = rffi.llexternal('int_to_void_p', [rffi.INT], lltype.Ptr(lltype.FixedSizeArray(lltype.Void, 1)))
+        c_int_to_void_p = rffi.llexternal('int_to_void_p', [rffi.INT], rffi.VOIDP)
         """)
 
-        assert src == _src, str(src) + "\n" + str(_src)
+        assert src.code == _src, str(src) + "\n" + str(_src)
+
+    def test_struct_return(self):
+        func = self.lib.int_int_to_struct_p
+        func.argtypes = [ctypes.c_int, ctypes.c_int]
+        func.restype = ctypes.POINTER(random_structure)
+        rffi_source = RffiSource()
+        rffi_source.proc_func(func)
+        assert random_structure in rffi_source.structures
+        _src = py.code.Source("""
+        c_int_int_to_struct_p = rffi.llexternal('int_int_to_struct_p', [rffi.INT, rffi.INT], lltype.Ptr(c_random_structure))
+        """)
+        src = rffi_source.code
+        assert src.strip() == _src.strip(), str(src) + "\n" + str(_src)



More information about the Pypy-commit mailing list