Author: Armin Rigo <ar...@tunes.org> Branch: Changeset: r371:6c37945392dd Date: 2012-06-15 19:47 +0200 http://bitbucket.org/cffi/cffi/changeset/6c37945392dd/
Log: Global variables. Needed a bit of refactoring: we cannot return directly the extension module any more, because we need to have the global variable as a property. diff --git a/cffi/verifier.py b/cffi/verifier.py --- a/cffi/verifier.py +++ b/cffi/verifier.py @@ -78,12 +78,13 @@ lst = [revmapping[i] for i in range(len(revmapping))] lst = map(self.ffi._get_cached_btype, lst) dct = module._cffi_setup(lst, ffiplatform.VerificationError) - del module._cffi_setup - module.__dict__.update(dct) # - self.load(module, 'loaded') - # - return module + class FFILibrary(object): + pass + library = FFILibrary() + library.__dict__.update(dct) + self.load(module, 'loaded', library=library) + return library def generate(self, step_name): for name, tp in self.ffi._parser._declarations.iteritems(): @@ -91,16 +92,16 @@ method = getattr(self, 'generate_cpy_%s_%s' % (kind, step_name)) method(tp, realname) - def load(self, module, step_name): + def load(self, module, step_name, **kwds): for name, tp in self.ffi._parser._declarations.iteritems(): kind, realname = name.split(' ', 1) method = getattr(self, '%s_cpy_%s' % (step_name, kind)) - method(tp, realname, module) + method(tp, realname, module, **kwds) def generate_nothing(self, tp, name): pass - def loaded_noop(self, tp, name, module): + def loaded_noop(self, tp, name, module, **kwds): pass # ---------- @@ -213,8 +214,10 @@ meth = 'METH_VARARGS' self.prnt(' {"%s", _cffi_f_%s, %s},' % (name, name, meth)) - loading_cpy_function = loaded_noop - loaded_cpy_function = loaded_noop + loading_cpy_function = loaded_noop + + def loaded_cpy_function(self, tp, name, module, library): + setattr(library, name, getattr(module, name)) # ---------- # struct declarations @@ -311,7 +314,7 @@ assert len(fieldofs) == len(fieldsize) == len(tp.fldnames) tp.fixedlayout = fieldofs, fieldsize, totalsize, totalalignment - def loaded_cpy_struct(self, tp, name, module): + def loaded_cpy_struct(self, tp, name, module, **kwds): if tp.fldnames is None: return # nothing to do with opaque structs self.ffi._get_cached_btype(tp) # force 'fixedlayout' to be considered @@ -330,16 +333,23 @@ prnt(' return -1;') self.chained_list_constants = funcname - def _generate_cpy_const(self, is_int, name, tp=None): + def _generate_cpy_const(self, is_int, name, tp=None, category='const'): vardecls = ['PyObject *o;', 'int res;'] if not is_int: vardecls.append('%s;' % tp.get_c_name(' i')) - self._generate_chain_header('_cffi_const_%s' % name, *vardecls) + else: + assert category == 'const' + self._generate_chain_header('_cffi_%s_%s' % (category, name), + *vardecls) # prnt = self.prnt if not is_int: - prnt(' i = (%s);' % (name,)) + if category == 'var': + realexpr = '&' + name + else: + realexpr = name + prnt(' i = (%s);' % (realexpr,)) prnt(' o = %s;' % (self.convert_expr_from_c(tp, 'i'),)) else: prnt(' if (LONG_MIN <= (%s) && (%s) <= LONG_MAX)' % (name, name)) @@ -392,12 +402,15 @@ generate_cpy_enum_method = generate_nothing loading_cpy_enum = loaded_noop - def loaded_cpy_enum(self, tp, name, module): + def loaded_cpy_enum(self, tp, name, module, library): if tp.partial: - enumvalues = [getattr(module, enumerator) + enumvalues = [getattr(library, enumerator) for enumerator in tp.enumerators] tp.enumvalues = tuple(enumvalues) tp.partial = False + else: + for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues): + setattr(library, enumerator, enumvalue) # ---------- # macros: for now only for integers @@ -411,6 +424,27 @@ loaded_cpy_macro = loaded_noop # ---------- + # global variables + + def generate_cpy_variable_decl(self, tp, name): + tp_ptr = model.PointerType(tp) + self._generate_cpy_const(False, name, tp_ptr, category='var') + + generate_cpy_variable_method = generate_nothing + loading_cpy_variable = loaded_noop + + def loaded_cpy_variable(self, tp, name, module, library): + # remove ptr=<cdata 'int *'> from the library instance, and replace + # it by a property on the class, which reads/writes into ptr[0]. + ptr = getattr(library, name) + delattr(library, name) + def getter(library): + return ptr[0] + def setter(library, value): + ptr[0] = value + setattr(library.__class__, name, property(getter, setter)) + + # ---------- cffimod_header = r''' #include <Python.h> diff --git a/testing/test_verify.py b/testing/test_verify.py --- a/testing/test_verify.py +++ b/testing/test_verify.py @@ -332,7 +332,8 @@ "enum ee { EE1, EE3, EE2 };") assert str(e.value) == 'in enum ee: EE2 has the real value 2, not 1' # extra items cannot be seen and have no bad consequence anyway - ffi.verify("enum ee { EE1, EE2, EE3, EE4 };") + lib = ffi.verify("enum ee { EE1, EE2, EE3, EE4 };") + assert lib.EE3 == 2 def test_get_set_errno(): ffi = FFI() @@ -356,3 +357,19 @@ "#define BAR (-44)\n") assert lib.FOO == 42 assert lib.BAR == -44 + +def test_access_variable(): + ffi = FFI() + ffi.cdef("int foo(void);\n" + "int somenumber;") + lib = ffi.verify(""" + static int somenumber = 2; + static int foo(void) { + return somenumber * 7; + } + """) + assert lib.somenumber == 2 + assert lib.foo() == 14 + lib.somenumber = -6 + assert lib.foo() == -42 + assert lib.somenumber == -6 _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit