Author: Armin Rigo <[email protected]>
Branch:
Changeset: r597:ab05b68f4d1b
Date: 2012-07-08 12:04 +0200
http://bitbucket.org/cffi/cffi/changeset/ab05b68f4d1b/
Log: For interactive usage (playing around), add the option
ffi.cdef("..", override=True).
diff --git a/cffi/api.py b/cffi/api.py
--- a/cffi/api.py
+++ b/cffi/api.py
@@ -49,6 +49,7 @@
self._cached_btypes = {}
self._parsed_types = new.module('parsed_types').__dict__
self._new_types = new.module('new_types').__dict__
+ self._function_caches = []
if hasattr(backend, 'set_ffi'):
backend.set_ffi(self)
#
@@ -67,13 +68,16 @@
#
self.NULL = self.cast("void *", 0)
- def cdef(self, csource):
+ def cdef(self, csource, override=False):
"""Parse the given C source. This registers all declared functions,
types, and global variables. The functions and global variables can
then be accessed via either 'ffi.dlopen()' or 'ffi.verify()'.
The types can be used in 'ffi.new()' and other functions.
"""
- self._parser.parse(csource)
+ self._parser.parse(csource, override=override)
+ if override:
+ for cache in self._function_caches:
+ cache.clear()
def dlopen(self, name):
"""Load and return a dynamic library identified by 'name'.
@@ -83,7 +87,9 @@
library we only look for the actual (untyped) symbols.
"""
assert isinstance(name, str) or name is None
- return _make_ffi_library(self, name)
+ lib, function_cache = _make_ffi_library(self, name)
+ self._function_caches.append(function_cache)
+ return lib
def typeof(self, cdecl, consider_function_as_funcptr=False):
"""Parse the C type given as a string and return the
@@ -282,4 +288,4 @@
#
if libname is not None:
FFILibrary.__name__ = 'FFILibrary_%s' % libname
- return FFILibrary()
+ return FFILibrary(), function_cache
diff --git a/cffi/cparser.py b/cffi/cparser.py
--- a/cffi/cparser.py
+++ b/cffi/cparser.py
@@ -46,6 +46,7 @@
self._declarations = {}
self._anonymous_counter = 0
self._structnode2type = weakref.WeakKeyDictionary()
+ self._override = False
def _parse(self, csource):
# XXX: for more efficiency we would need to poke into the
@@ -63,7 +64,15 @@
ast = _get_parser().parse(csource)
return ast, macros
- def parse(self, csource):
+ def parse(self, csource, override=False):
+ prev_override = self._override
+ try:
+ self._override = override
+ self._internal_parse(csource)
+ finally:
+ self._override = prev_override
+
+ def _internal_parse(self, csource):
ast, macros = self._parse(csource)
# add the macros
for key, value in macros.items():
@@ -139,7 +148,10 @@
if name in self._declarations:
if self._declarations[name] is obj:
return
- raise api.FFIError("multiple declarations of %s" % (name,))
+ if not self._override:
+ raise api.FFIError(
+ "multiple declarations of %s (for interactive usage, "
+ "try cdef(xx, override=True))" % (name,))
assert name != '__dotdotdot__'
self._declarations[name] = obj
diff --git a/testing/test_parsing.py b/testing/test_parsing.py
--- a/testing/test_parsing.py
+++ b/testing/test_parsing.py
@@ -1,5 +1,5 @@
import py, sys
-from cffi import FFI, CDefError, VerificationError
+from cffi import FFI, FFIError, CDefError, VerificationError
class FakeBackend(object):
@@ -168,3 +168,12 @@
assert repr(type_bar) == "<struct $1>"
py.test.raises(VerificationError, type_bar.get_c_name)
assert type_foo.get_c_name() == "foo_t"
+
+def test_override():
+ ffi = FFI(backend=FakeBackend())
+ C = ffi.dlopen(None)
+ ffi.cdef("int foo(void);")
+ py.test.raises(FFIError, ffi.cdef, "long foo(void);")
+ assert C.foo.BType == '<func (), <int>, False>'
+ ffi.cdef("long foo(void);", override=True)
+ assert C.foo.BType == '<func (), <long>, False>'
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit