Author: Armin Rigo <[email protected]>
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
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit