Author: Armin Rigo <ar...@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 _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit