[pypy-commit] pypy cffi-1.0: Starting on lib_obj

arigo noreply at buildbot.pypy.org
Fri May 8 00:38:45 CEST 2015


Author: Armin Rigo <arigo at tunes.org>
Branch: cffi-1.0
Changeset: r77186:b8545eb63d96
Date: 2015-05-08 00:38 +0200
http://bitbucket.org/pypy/pypy/changeset/b8545eb63d96/

Log:	Starting on lib_obj

diff --git a/pypy/module/_cffi_backend/cffi1_module.py b/pypy/module/_cffi_backend/cffi1_module.py
--- a/pypy/module/_cffi_backend/cffi1_module.py
+++ b/pypy/module/_cffi_backend/cffi1_module.py
@@ -5,6 +5,7 @@
 from pypy.interpreter.module import Module
 from pypy.module._cffi_backend import parse_c_type
 from pypy.module._cffi_backend.ffi_obj import W_FFIObject
+from pypy.module._cffi_backend.lib_obj import W_LibObject
 
 
 EXPECTED_VERSION = 0x10000f0
@@ -28,10 +29,11 @@
         raise
 
     ffi = W_FFIObject(space, src_ctx)
+    lib = W_LibObject(ffi, name)
 
     w_name = space.wrap(name)
     module = Module(space, w_name)
     module.setdictvalue(space, '__file__', space.wrap(path))
     module.setdictvalue(space, 'ffi', space.wrap(ffi))
-    module.setdictvalue(space, 'lib', space.w_None)
+    module.setdictvalue(space, 'lib', space.wrap(lib))
     space.setitem(space.sys.get('modules'), w_name, space.wrap(module))
diff --git a/pypy/module/_cffi_backend/lib_obj.py b/pypy/module/_cffi_backend/lib_obj.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/_cffi_backend/lib_obj.py
@@ -0,0 +1,78 @@
+from rpython.rlib import jit
+from rpython.rtyper.lltypesystem import rffi
+
+from pypy.interpreter.error import oefmt
+from pypy.interpreter.baseobjspace import W_Root
+from pypy.interpreter.typedef import TypeDef
+from pypy.interpreter.gateway import interp2app
+
+from pypy.module._cffi_backend import parse_c_type, realize_c_type, cffi_opcode
+from pypy.module._cffi_backend.realize_c_type import getop, getarg
+from pypy.module._cffi_backend.cdataobj import W_CData
+
+
+class W_LibObject(W_Root):
+
+    def __init__(self, ffi, libname):
+        self.space = ffi.space
+        self.ctx = ffi.ctxobj.ctx
+        self.ffi = ffi
+        self.dict_w = {}          # content, built lazily
+        self.libname = libname    # some string that gives the name of the lib
+        self.includes = []        # list of W_LibObjects included here
+
+    def descr_repr(self):
+        XXX
+
+    @jit.elidable_promote()
+    def _get_attr(self, attr):
+        try:
+            w_result = self.dict_w[attr]
+        except KeyError:
+            index = parse_c_type.search_in_globals(self.ctx, attr)
+            if index < 0:
+                return None     # no active caching, but still @elidable
+
+            g = self.ctx.c_globals[index]
+            op = getop(g.c_type_op)
+            if (op == cffi_opcode.OP_CPYTHON_BLTN_V or
+                op == cffi_opcode.OP_CPYTHON_BLTN_N or
+                op == cffi_opcode.OP_CPYTHON_BLTN_O):
+                #
+                type_index = getarg(g.c_type_op)
+                opcodes = self.ctx.c_types
+                w_ct = realize_c_type.realize_c_type_or_func(self.ffi, opcodes,
+                                                             type_index)
+                w_ct = realize_c_type.unwrap_fn_as_fnptr(w_ct)
+                ptr = rffi.cast(rffi.CCHARP, g.c_address)
+                w_result = W_CData(self.space, ptr, w_ct)
+                #
+            else:
+                raise NotImplementedError("in lib_build_attr: op=%d" % op)
+            
+            self.dict_w[attr] = w_result
+        return w_result
+
+    def _no_such_attr(self, attr):
+        raise oefmt(self.space.w_AttributeError,
+                    "cffi lib '%s' has no function,"
+                    " global variable or constant named '%s'",
+                    self.libname, attr)
+
+    def descr_getattribute(self, w_attr):
+        space = self.space
+        attr = space.str_w(w_attr)
+        w_value = self._get_attr(attr)
+        if w_value is None:
+            raise self._no_such_attr(attr)
+        #elif isinstance(w_value, Globxxx):
+        #    ...
+        return w_value
+
+
+W_LibObject.typedef = TypeDef(
+        'CompiledLib',
+        __repr__ = interp2app(W_LibObject.descr_repr),
+        __getattribute__ = interp2app(W_LibObject.descr_getattribute),
+        )
+W_LibObject.acceptable_as_base_class = False
diff --git a/pypy/module/_cffi_backend/parse_c_type.py b/pypy/module/_cffi_backend/parse_c_type.py
--- a/pypy/module/_cffi_backend/parse_c_type.py
+++ b/pypy/module/_cffi_backend/parse_c_type.py
@@ -18,10 +18,11 @@
     return rffi.llexternal(name, args, result, compilation_info=eci,
                            _nowrapper=True, **kwds)
 
+_CFFI_OPCODE_T = rffi.VOIDP
 GLOBAL_S = rffi.CStruct('struct _cffi_global_s',
                        ('name', rffi.CCHARP),
                        ('address', rffi.VOIDP),
-                       ('type_op', rffi.SIGNED),
+                       ('type_op', _CFFI_OPCODE_T),
                        ('size', rffi.SIZE_T))
 STRUCT_UNION_S = rffi.CStruct('struct _cffi_struct_union_s',
                        ('name', rffi.CCHARP),
@@ -31,7 +32,12 @@
                        ('alignment', rffi.INT),
                        ('first_field_index', rffi.INT),
                        ('num_fields', rffi.INT))
-FIELD_S = rffi.CStruct('struct _cffi_field_s')
+FIELD_S = rffi.CStruct('struct _cffi_field_s',
+    ## const char *name;
+    ## size_t field_offset;
+    ## size_t field_size;
+    ## _cffi_opcode_t field_type_op;
+    )
 ENUM_S = rffi.CStruct('struct _cffi_enum_s',
                        ('name', rffi.CCHARP),
                        ('type_index', rffi.INT),
@@ -62,7 +68,11 @@
                         ('error_location', rffi.SIZE_T),
                         ('error_message', rffi.CCHARP))
 
-ll_parse_c_type = llexternal('parse_c_type', [PINFO, rffi.CCHARP], rffi.INT)
+ll_parse_c_type = llexternal('pypy_parse_c_type', [PINFO, rffi.CCHARP],
+                             rffi.INT)
+ll_search_in_globals = llexternal('pypy_search_in_globals',
+                                  [PCTX, rffi.CCHARP, rffi.SIZE_T],
+                                  rffi.INT)
 
 def parse_c_type(info, input):
     p_input = rffi.str2charp(input)
@@ -96,3 +106,10 @@
 
 def get_num_types(src_ctx):
     return rffi.getintfield(src_ctx, 'c_num_types')
+
+def search_in_globals(ctx, name):
+    c_name = rffi.str2charp(name)
+    result = ll_search_in_globals(ctx, c_name,
+                                  rffi.cast(rffi.SIZE_T, len(name)))
+    rffi.free_charp(c_name)
+    return rffi.cast(lltype.Signed, result)
diff --git a/pypy/module/_cffi_backend/src/parse_c_type.c b/pypy/module/_cffi_backend/src/parse_c_type.c
--- a/pypy/module/_cffi_backend/src/parse_c_type.c
+++ b/pypy/module/_cffi_backend/src/parse_c_type.c
@@ -7,6 +7,10 @@
 #define _CFFI_INTERNAL
 #include "src/precommondefs.h"
 #include "parse_c_type.h"
+#define search_in_globals       pypy_search_in_globals
+#define search_in_struct_unions pypy_search_in_struct_unions
+#define search_in_typenames     pypy_search_in_typenames
+#define search_in_enums         pypy_search_in_enums
 
 
 enum token_e {
@@ -408,8 +412,8 @@
 
 
 #define MAKE_SEARCH_FUNC(FIELD)                                 \
-  static                                                        \
-  int search_in_##FIELD(const struct _cffi_type_context_s *ctx, \
+  RPY_EXTERN int                                                \
+  pypy_search_in_##FIELD(const struct _cffi_type_context_s *ctx,\
                         const char *search, size_t search_len)  \
   {                                                             \
       int left = 0, right = ctx->num_##FIELD;                   \
@@ -734,7 +738,7 @@
 
 
 RPY_EXTERN
-int parse_c_type(struct _cffi_parse_info_s *info, const char *input)
+int pypy_parse_c_type(struct _cffi_parse_info_s *info, const char *input)
 {
     int result;
     token_t token;
diff --git a/pypy/module/_cffi_backend/src/parse_c_type.h b/pypy/module/_cffi_backend/src/parse_c_type.h
--- a/pypy/module/_cffi_backend/src/parse_c_type.h
+++ b/pypy/module/_cffi_backend/src/parse_c_type.h
@@ -142,9 +142,12 @@
 };
 
 #ifdef _CFFI_INTERNAL
-RPY_EXTERN int parse_c_type(struct _cffi_parse_info_s *info, const char *input);
-static int search_in_globals(const struct _cffi_type_context_s *ctx,
+RPY_EXTERN int
+pypy_parse_c_type(struct _cffi_parse_info_s *info, const char *input);
+RPY_EXTERN int
+pypy_search_in_globals(const struct _cffi_type_context_s *ctx,
+                       const char *search, size_t search_len);
+RPY_EXTERN int
+pypy_search_in_struct_unions(const struct _cffi_type_context_s *ctx,
                              const char *search, size_t search_len);
-static int search_in_struct_unions(const struct _cffi_type_context_s *ctx,
-                                   const char *search, size_t search_len);
 #endif


More information about the pypy-commit mailing list