[pypy-commit] cffi default: Keep the loaded libraries alive as long as the 'ffi' object is kept alive.
arigo
noreply at buildbot.pypy.org
Tue Oct 9 11:20:38 CEST 2012
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r990:a4f49af3db3c
Date: 2012-10-09 11:18 +0200
http://bitbucket.org/cffi/cffi/changeset/a4f49af3db3c/
Log: Keep the loaded libraries alive as long as the 'ffi' object is kept
alive.
diff --git a/cffi/api.py b/cffi/api.py
--- a/cffi/api.py
+++ b/cffi/api.py
@@ -50,6 +50,7 @@
self._parsed_types = types.ModuleType('parsed_types').__dict__
self._new_types = types.ModuleType('new_types').__dict__
self._function_caches = []
+ self._libraries = []
self._cdefsources = []
self._pointer_type_cache = {}
if hasattr(backend, 'set_ffi'):
@@ -97,6 +98,7 @@
assert isinstance(name, str) or name is None
lib, function_cache = _make_ffi_library(self, name, flags)
self._function_caches.append(function_cache)
+ self._libraries.append(lib)
return lib
def _typeof(self, cdecl, consider_function_as_funcptr=False):
@@ -281,7 +283,9 @@
from .verifier import Verifier, _caller_dir_pycache
tmpdir = tmpdir or _caller_dir_pycache()
self.verifier = Verifier(self, source, tmpdir, **kwargs)
- return self.verifier.load_library()
+ lib = self.verifier.load_library()
+ self._libraries.append(lib)
+ return lib
def _get_errno(self):
return self._backend.get_errno()
diff --git a/cffi/vengine_cpy.py b/cffi/vengine_cpy.py
--- a/cffi/vengine_cpy.py
+++ b/cffi/vengine_cpy.py
@@ -140,6 +140,7 @@
# pointers, and store them as attributes on the 'library' object.
class FFILibrary(object):
_cffi_python_module = module
+ _cffi_ffi = self.ffi
library = FFILibrary()
module._cffi_setup(lst, ffiplatform.VerificationError, library)
#
diff --git a/cffi/vengine_gen.py b/cffi/vengine_gen.py
--- a/cffi/vengine_gen.py
+++ b/cffi/vengine_gen.py
@@ -53,6 +53,7 @@
# build the FFILibrary class and instance
class FFILibrary(object):
_cffi_generic_module = module
+ _cffi_ffi = self.ffi
library = FFILibrary()
#
# finally, call the loaded_gen_xxx() functions. This will set
diff --git a/testing/test_ownlib.py b/testing/test_ownlib.py
--- a/testing/test_ownlib.py
+++ b/testing/test_ownlib.py
@@ -1,5 +1,5 @@
import py, sys
-import subprocess
+import subprocess, weakref
from cffi import FFI
from cffi.backend_ctypes import CTypesBackend
@@ -98,3 +98,40 @@
ownlib.my_array = list(range(7))
for i in range(7):
assert ownlib.my_array[i] == i
+
+ def test_keepalive_lib(self):
+ if sys.platform == 'win32':
+ py.test.skip("fix the auto-generation of the tiny test lib")
+ ffi = FFI(backend=self.Backend())
+ ffi.cdef("""
+ int test_getting_errno(void);
+ """)
+ ownlib = ffi.dlopen(self.module)
+ ffi_r = weakref.ref(ffi)
+ ownlib_r = weakref.ref(ownlib)
+ func = ownlib.test_getting_errno
+ del ffi
+ import gc; gc.collect() # ownlib stays alive
+ assert ownlib_r() is not None
+ assert ffi_r() is not None # kept alive by ownlib
+ res = func()
+ assert res == -1
+
+ def test_keepalive_ffi(self):
+ if sys.platform == 'win32':
+ py.test.skip("fix the auto-generation of the tiny test lib")
+ ffi = FFI(backend=self.Backend())
+ ffi.cdef("""
+ int test_getting_errno(void);
+ """)
+ ownlib = ffi.dlopen(self.module)
+ ffi_r = weakref.ref(ffi)
+ ownlib_r = weakref.ref(ownlib)
+ func = ownlib.test_getting_errno
+ del ownlib
+ import gc; gc.collect() # ffi stays alive
+ assert ffi_r() is not None
+ assert ownlib_r() is not None # kept alive by ffi
+ res = func()
+ assert res == -1
+ assert ffi.errno == 123
diff --git a/testing/test_verify.py b/testing/test_verify.py
--- a/testing/test_verify.py
+++ b/testing/test_verify.py
@@ -1,5 +1,5 @@
import py
-import sys, math
+import sys, math, weakref
from cffi import FFI, VerificationError, VerificationMissing, model
from testing.support import *
@@ -1192,3 +1192,29 @@
g = subprocess.Popen([sys.executable, arg])
result = g.wait()
assert result == 0
+
+def test_keepalive_lib():
+ ffi = FFI()
+ ffi.cdef("int foobar(void);")
+ lib = ffi.verify("int foobar(void) { return 42; }")
+ func = lib.foobar
+ ffi_r = weakref.ref(ffi)
+ lib_r = weakref.ref(lib)
+ del ffi
+ import gc; gc.collect() # lib stays alive
+ assert lib_r() is not None
+ assert ffi_r() is not None
+ assert func() == 42
+
+def test_keepalive_ffi():
+ ffi = FFI()
+ ffi.cdef("int foobar(void);")
+ lib = ffi.verify("int foobar(void) { return 42; }")
+ func = lib.foobar
+ ffi_r = weakref.ref(ffi)
+ lib_r = weakref.ref(lib)
+ del lib
+ import gc; gc.collect() # ffi stays alive
+ assert ffi_r() is not None
+ assert lib_r() is not None
+ assert func() == 42
More information about the pypy-commit
mailing list