[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