[pypy-commit] pypy cffi-1.0: Tweaks to end up in _cffi_backend when loading C extension modules
arigo
noreply at buildbot.pypy.org
Thu May 7 16:48:46 CEST 2015
Author: Armin Rigo <arigo at tunes.org>
Branch: cffi-1.0
Changeset: r77179:90b0f73648e7
Date: 2015-05-07 16:48 +0200
http://bitbucket.org/pypy/pypy/changeset/90b0f73648e7/
Log: Tweaks to end up in _cffi_backend when loading C extension modules
that declare "_cffi_pypyinit_%s()" instead of "init%s()".
diff --git a/pypy/module/_cffi_backend/cffi1_module.py b/pypy/module/_cffi_backend/cffi1_module.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/_cffi_backend/cffi1_module.py
@@ -0,0 +1,4 @@
+
+def load_cffi1_module(space, name, dll, initptr):
+ xxxx
+
diff --git a/pypy/module/_cffi_backend/ctypestruct.py b/pypy/module/_cffi_backend/ctypestruct.py
--- a/pypy/module/_cffi_backend/ctypestruct.py
+++ b/pypy/module/_cffi_backend/ctypestruct.py
@@ -44,7 +44,7 @@
raise oefmt(w_errorcls or space.w_TypeError,
"'%s' is opaque or not completed yet", self.name)
- def force_lazy_struct(self, w_errorcls=None):
+ def force_lazy_struct(self):
# Force a "lazy" struct to become "forced"; complain if we are "opaque".
if self._fields_list is None:
self.check_complete()
diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -1113,30 +1113,66 @@
initfunctype = lltype.Ptr(lltype.FuncType([], lltype.Void))
@unwrap_spec(path=str, name=str)
def load_extension_module(space, path, name):
+ # note: this is used both to load CPython-API-style C extension
+ # modules (cpyext) and to load CFFI-style extension modules
+ # (_cffi_backend). Any of the two can be disabled at translation
+ # time, though. For this reason, we need to be careful about the
+ # order of things here.
+ from rpython.rlib import rdynload
+
if os.sep not in path:
path = os.curdir + os.sep + path # force a '/' in the path
+ basename = name.split('.')[-1]
+ try:
+ ll_libname = rffi.str2charp(path)
+ try:
+ dll = rdynload.dlopen(ll_libname)
+ finally:
+ lltype.free(ll_libname, flavor='raw')
+ except rdynload.DLOpenError, e:
+ raise oefmt(space.w_ImportError,
+ "unable to load extension module '%s': %s",
+ path, e.msg)
+ look_for = None
+ #
+ if space.config.objspace.usemodules._cffi_backend:
+ look_for = '_cffi_pypyinit_%s' % (basename,)
+ try:
+ initptr = rdynload.dlsym(dll, look_for)
+ except KeyError:
+ pass
+ else:
+ from pypy.module._cffi_backend.cffi1_module import load_cffi1_module
+ return load_cffi1_module(space, name, dll, initptr)
+ #
+ if space.config.objspace.usemodules.cpyext:
+ also_look_for = 'init%s' % (basename,)
+ try:
+ initptr = rdynload.dlsym(dll, also_look_for)
+ except KeyError:
+ pass
+ else:
+ return load_cpyext_module(space, name, dll, initptr)
+ if look_for is not None:
+ look_for += ' or ' + also_look_for
+ else:
+ look_for = also_look_for
+ #
+ raise oefmt(space.w_ImportError,
+ "function %s not found in library %s", look_for, path)
+
+
+def load_cpyext_module(space, name, dll, initptr):
+ from rpython.rlib import rdynload
+
+ space.getbuiltinmodule("cpyext") # mandatory to init cpyext
state = space.fromcache(State)
if state.find_extension(name, path) is not None:
+ rdynload.dlclose(dll)
return
old_context = state.package_context
state.package_context = name, path
try:
- from rpython.rlib import rdynload
- try:
- ll_libname = rffi.str2charp(path)
- try:
- dll = rdynload.dlopen(ll_libname)
- finally:
- lltype.free(ll_libname, flavor='raw')
- except rdynload.DLOpenError, e:
- raise oefmt(space.w_ImportError,
- "unable to load extension module '%s': %s",
- path, e.msg)
- try:
- initptr = rdynload.dlsym(dll, 'init%s' % (name.split('.')[-1],))
- except KeyError:
- raise oefmt(space.w_ImportError,
- "function init%s not found in library %s", name, path)
initfunc = rffi.cast(initfunctype, initptr)
generic_cpy_call(space, initfunc)
state.check_and_raise_exception()
diff --git a/pypy/module/imp/importing.py b/pypy/module/imp/importing.py
--- a/pypy/module/imp/importing.py
+++ b/pypy/module/imp/importing.py
@@ -51,6 +51,10 @@
"""Tests whether the given path is an existing regular file."""
return os.path.isfile(path) and case_ok(path)
+def has_so_extension(space):
+ return (space.config.objspace.usemodules.cpyext or
+ space.config.objspace.usemodules._cffi_backend)
+
def find_modtype(space, filepart):
"""Check which kind of module to import for the given filepart,
which is a path without extension. Returns PY_SOURCE, PY_COMPILED or
@@ -79,7 +83,7 @@
# existing .pyc file
return PY_COMPILED, ".pyc", "rb"
- if space.config.objspace.usemodules.cpyext:
+ if has_so_extension(space):
so_extension = get_so_extension(space)
pydfile = filepart + so_extension
if file_exists(pydfile):
@@ -565,10 +569,9 @@
return w_mod
def load_c_extension(space, filename, modulename):
- # the next line is mandatory to init cpyext
- space.getbuiltinmodule("cpyext")
from pypy.module.cpyext.api import load_extension_module
load_extension_module(space, filename, modulename)
+ # NB. cpyext.api.load_extension_module() can also delegate to _cffi_backend
@jit.dont_look_inside
def load_module(space, w_modulename, find_info, reuse=False):
@@ -628,7 +631,7 @@
# fetch the module again, in case of "substitution"
w_mod = check_sys_modules(space, w_modulename)
return w_mod
- elif find_info.modtype == C_EXTENSION and space.config.objspace.usemodules.cpyext:
+ elif find_info.modtype == C_EXTENSION and has_so_extension(space):
load_c_extension(space, find_info.filename, space.str_w(w_modulename))
return check_sys_modules(space, w_modulename)
except OperationError:
diff --git a/pypy/module/imp/interp_imp.py b/pypy/module/imp/interp_imp.py
--- a/pypy/module/imp/interp_imp.py
+++ b/pypy/module/imp/interp_imp.py
@@ -11,7 +11,7 @@
def get_suffixes(space):
w = space.wrap
suffixes_w = []
- if space.config.objspace.usemodules.cpyext:
+ if importing.has_so_extension(space):
suffixes_w.append(
space.newtuple([w(importing.get_so_extension(space)),
w('rb'), w(importing.C_EXTENSION)]))
@@ -128,7 +128,7 @@
@unwrap_spec(filename=str)
def load_dynamic(space, w_modulename, filename, w_file=None):
- if not space.config.objspace.usemodules.cpyext:
+ if not importing.has_so_extension(space):
raise OperationError(space.w_ImportError, space.wrap(
"Not implemented"))
importing.load_c_extension(space, filename, space.str_w(w_modulename))
More information about the pypy-commit
mailing list